bug fixes

design_3.0_latest
WaseemAbbasi22 7 months ago
parent 6b93479170
commit a66215ef8b

@ -3,12 +3,12 @@ class URLs {
static const String appReleaseBuildNumber = "14";
// static const host1 = "https://atomsm.hmg.com"; // production url
// static const host1 = "https://atomsmdev.hmg.com"; // local DEV url
static const host1 = "https://atomsmuat.hmg.com"; // local UAT url
static const host1 = "https://atomsmdev.hmg.com"; // local DEV url
// static const host1 = "https://atomsmuat.hmg.com"; // local UAT url
// static String _baseUrl = "$_host/mobile";
// 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/mobile"; // host local UAT
// static final String _baseUrl = "$_host/v3/mobile"; // new V3 apis
static String _host = host1;

@ -549,6 +549,14 @@
"attachments": "المرفقات",
"supplierName": "اسم المورد",
"externalEngineerName": "اسم المهندس الخارجي",
"telephone": "الهاتف"
"telephone": "الهاتف",
"arrivedDate": "تاريخ الوصول",
"closedDate": "تاريخ الإغلاق",
"since": "منذ",
"rejectionDetails": "تفاصيل الرفض",
"part": "جزء",
"closedDate": "تاريخ الإغلاق",
"creationDate": "تاريخ الإنشاء"
}

@ -552,5 +552,13 @@
"attachments": "Attachments",
"supplierName": "Supplier Name",
"externalEngineerName": "External Engineer Name",
"telephone": "Telephone"
"telephone": "Telephone",
"arrivedDate": "Arrived Date",
"closedDate": "Closed Date",
"since": "Since",
"rejectionDetails": "Rejection Details",
"part": "Part",
"closedDate": "Closed Date",
"creationDate": "Creation Date"
}

@ -84,6 +84,13 @@ class WorkOrderData {
required this.totalWorkingHours,
this.needAVisitComment,
this.needAVisitDateTime,
this.iHaveArrivedDate,
this.rejectReason,
this.closedDate,
this.since,
this.cmFrame,
this.lastComment,
this.callResponse,
required this.workOrderHistory,
required this.activities,
required this.activityAssetToBeRetireds,
@ -127,9 +134,18 @@ class WorkOrderData {
Lookup? failureReasone;
FaultDescription? faultDescription;
Lookup? solution;
Lookup? cmFrame;
//cmComments
String? totalWorkingHours;
DateTime? needAVisitDateTime;
String? needAVisitComment;
String? iHaveArrivedDate;
String? closedDate;
Lookup? rejectReason;
String? lastComment; // need to replace with reject comments.
String? callResponse; // need to replace with reject comments.
int? since;
List<WorkOrderHistory> workOrderHistory;
List<Activities> activities;
List<dynamic> activityAssetToBeRetireds;
@ -150,6 +166,13 @@ class WorkOrderData {
floor: json["floor"] == null ? null : Lookup.fromJson(json["floor"]),
department: json["department"] == null ? null : AssetGroup.fromJson(json["department"]),
room: json["room"],
lastComment: json["lastComment"],
callResponse: json["callResponse"],
iHaveArrivedDate: json["iHaveArrivedDate"],
closedDate: json["closedDate"],
cmFrame: json["cmFrame"] == null ? null : Lookup.fromJson(json["cmFrame"]),
rejectReason: json["rejectReason"] == null ? null : Lookup.fromJson(json["rejectReason"]),
since: json['since'],
assetType: json["assetType"] == null ? null : Lookup.fromJson(json["assetType"]),
assignedEmployee: json["assignedEmployee"] == null ? null : WorkOrderAssignedEmployee.fromJson(json["assignedEmployee"]),
lastActivityStatus: json["lastActivityStatus"] != null ? Lookup.fromJson(json["lastActivityStatus"]) : null,
@ -174,7 +197,7 @@ class WorkOrderData {
failureReasone: json["failureReasone"] == null ? null : Lookup.fromJson(json["failureReasone"]),
faultDescription: json["faultDescription"] == null ? null : FaultDescription.fromJson(json["faultDescription"]),
solution: json["solution"] == null ? null : Lookup.fromJson(json["solution"]),
totalWorkingHours: (json["totalWorkingHours"] ??"").toString(),
totalWorkingHours: (json["totalWorkingHours"] ?? "").toString(),
workOrderHistory: json["workOrderHistory"] == null ? [] : List<WorkOrderHistory>.from(json["workOrderHistory"]!.map((x) => WorkOrderHistory.fromJson(x))),
activities: json["activities"] == null ? [] : List<Activities>.from(json["activities"]!.map((x) => Activities.fromJson(x))),
needAVisitDateTime: DateTime.tryParse(json["needAVisitDateTime"] ?? ""),

@ -3,6 +3,7 @@ import 'dart:io';
import 'package:flutter/widgets.dart';
import 'package:fluttertoast/fluttertoast.dart';
import 'package:test_sa/extensions/context_extension.dart';
import 'package:test_sa/models/device/asset.dart';
import 'package:test_sa/models/lookup.dart';
import 'package:test_sa/models/service_request/supplier_details.dart';
import 'package:test_sa/models/timer_model.dart';
@ -24,6 +25,8 @@ class PlanPreventiveVisit {
String? departmentName;
String? roomName;
String? fromDate;
String? creationDate;
String? closedDate;
String? toDate;
AssignedEmployee? assignedEmployee;
DateTime? acutalDateOfVisit;
@ -65,6 +68,8 @@ class PlanPreventiveVisit {
this.departmentName,
this.roomName,
this.fromDate,
this.creationDate,
this.closedDate,
this.toDate,
this.assignedEmployee,
this.acutalDateOfVisit,
@ -105,6 +110,8 @@ class PlanPreventiveVisit {
departmentName = json['departmentName'];
roomName = json['roomName'];
fromDate = json['fromDate'];
creationDate = json['creationDate'];
closedDate = json['closedDate'];
toDate = json['toDate'];
assignedEmployee = json['assignedEmployee'] != null ? AssignedEmployee.fromJson(json['assignedEmployee']) : null;
acutalDateOfVisit = json['acutalDateOfVisit'] != null ? DateTime.parse(json['acutalDateOfVisit']) : null;
@ -526,27 +533,27 @@ class PlanPreventiveVisit {
// }
// }
class Asset {
num? id;
String? assetNumber;
String? assetSerialNo;
Asset({this.id, this.assetNumber, this.assetSerialNo});
Asset.fromJson(Map<String, dynamic> json) {
id = json['id'];
assetNumber = json['assetNumber'];
assetSerialNo = json['assetSerialNo'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = Map<String, dynamic>();
data['id'] = this.id;
data['assetNumber'] = this.assetNumber;
data['assetSerialNo'] = this.assetSerialNo;
return data;
}
}
// class Asset {
// num? id;
// String? assetNumber;
// String? assetSerialNo;
//
// Asset({this.id, this.assetNumber, this.assetSerialNo});
//
// Asset.fromJson(Map<String, dynamic> json) {
// id = json['id'];
// assetNumber = json['assetNumber'];
// assetSerialNo = json['assetSerialNo'];
// }
//
// Map<String, dynamic> toJson() {
// final Map<String, dynamic> data = Map<String, dynamic>();
// data['id'] = this.id;
// data['assetNumber'] = this.assetNumber;
// data['assetSerialNo'] = this.assetSerialNo;
// return data;
// }
// }
class AssignedEmployee {
String? userId;

@ -53,6 +53,8 @@ class RecurrentWoData {
TimerModel? recurrentWoTimerModel = TimerModel();
double? totalWorkingHours = 0.0;
List<TimerModel>? timerModelList = [];
String? comment;
RecurrentWoData(
{this.id,
@ -70,6 +72,7 @@ class RecurrentWoData {
this.planRecurrentMedicalTaskRooms,
this.planRecurrentTaskTimers,
this.timerModelList,
this.comment,
this.totalWorkingHours});
RecurrentWoData.fromJson(Map<String, dynamic> json) {
@ -84,6 +87,7 @@ class RecurrentWoData {
floor = json["floor"] == null ? null : Lookup.fromJson(json["floor"]);
department = json["department"] == null ? null : Lookup.fromJson(json["department"]);
room = json["room"] == null ? null : Lookup.fromJson(json["room"]);
comment = json["comment"];
if (json['planRecurrentMedicalTaskRooms'] != null) {
planRecurrentMedicalTaskRooms = <PlanRecurrentMedicalTaskRooms>[];
json['planRecurrentMedicalTaskRooms'].forEach((v) {
@ -114,6 +118,7 @@ class RecurrentWoData {
}
data['id'] = id;
data['statusValue'] = status;
data['comment'] = comment;
if (planRecurrentTaskTimers != null) {
data['planRecurrentTaskTimers'] = planRecurrentTaskTimers!.map((v) => v.toJson()).toList();

@ -79,6 +79,7 @@ class AppColor {
static const Color orange50 = Color(0xffCC9B14);
static const Color orange60 = Color(0xff886400);
static const Color orange70 = Color(0xffFFC945);
static const Color orange80 = Color(0xff65531B);
// static Color greenStatus(BuildContext context) => context.isDark ? const Color(0xff1FA269) : green50;
static Color greenStatus(BuildContext context) => context.isDark ? const Color(0xff54C166) : green70.withOpacity(.5);

@ -185,7 +185,15 @@ class ServiceRequestDetailProvider extends ChangeNotifier {
notifyListeners();
}
//create workOrder nurse .....
bool _isReadOnlyRequest = false;
bool get isReadOnlyRequest => _isReadOnlyRequest;
set isReadOnlyRequest(bool value) {
_isReadOnlyRequest = value;
notifyListeners();
} //create workOrder nurse .....
Future<int> createWorkOrder() async {
isLoading = true;
notifyListeners();
@ -217,6 +225,11 @@ class ServiceRequestDetailProvider extends ChangeNotifier {
stateCode = response.statusCode;
if (response.statusCode >= 200 && response.statusCode < 300) {
currentWorkOrder = WorkOrderDetail.fromJson(json.decode(response.body));
if (currentWorkOrder?.data?.status?.id == 3498) {
isReadOnlyRequest = true;
} else {
isReadOnlyRequest = false;
}
}
isLoading = false;
notifyListeners();

@ -8,6 +8,7 @@ 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/workorder/work_order_helper_models.dart';
import 'package:test_sa/models/lookup.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';
@ -34,10 +35,10 @@ class FooterActionButton {
{required WorkOrderNextStepEnum workOrderNextStepStatus,
List<Activities> activities = const [],
required BuildContext context,
Lookup? status,
required UserProvider userProvider,
bool isEmpIsAssigned = false}) {
ServiceRequestDetailProvider requestDetailProvider = Provider.of<ServiceRequestDetailProvider>(context, listen: false);
bool showMarkAsFixedButton = activities.isEmpty ? false : activities.any((object) => object.activityStatus!.value == 14 || object.activityStatus!.value == 19);
if (userProvider.user?.type == UsersTypes.engineer) {
if (workOrderNextStepStatus == WorkOrderNextStepEnum.assignToMe && isEmpIsAssigned) return const SizedBox();
@ -58,6 +59,19 @@ class FooterActionButton {
// TODO: Handle this case.
case WorkOrderNextStepEnum.nTakeAction:
// const SizedBox().flushBar(context: context, title: context.translation.youMarkedThisIssueAsFixedWaitingForTheRequesterToConfirm, message: '');
//Need to add enum for these values in future instead of static values..
if (requestDetailProvider.isReadOnlyRequest) {
return footerContainer(
child: AppFilledButton(
label: context.translation.activities,
buttonColor: AppColor.neutral50,
onPressed: () async {
Navigator.push(context, MaterialPageRoute(builder: (context) => const ActivitiesListView()));
},
),
);
}
return footerContainer(
child: AppFilledButton(
label: context.translation.close,

@ -68,7 +68,7 @@ class _ActivitiesListViewState extends State<ActivitiesListView> {
//backgroundColor: const Color(0xfff8f9fb),
body: Consumer<ServiceRequestDetailProvider>(builder: (context, ServiceRequestDetailProvider requestDetailProvider, child) {
activities = requestDetailProvider.currentWorkOrder!.data!.activities;
requestDetailProvider.lastVisitedRequestActivityId = (activities.isNotEmpty? activities.last.id :-1)!;
requestDetailProvider.lastVisitedRequestActivityId = (activities.isNotEmpty ? activities.last.id : -1)!;
if (activities.isNotEmpty && (activities.last.activityStatus!.value == 14 || activities.last.activityStatus!.value == 19)) {
disableNewActivity = true;
} else {
@ -165,7 +165,7 @@ class _ActivitiesListViewState extends State<ActivitiesListView> {
// backgroundColor: AppColor.getHistoryLogStatusColorByName(activity.activityStatus!.name!),
backgroundColor: AppColor.primary10,
),
"drag_icon".toSvgAsset(height: 12, width: 23, color: AppColor.neutral160),
// "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,
@ -225,11 +225,6 @@ class _ActivitiesListViewState extends State<ActivitiesListView> {
style: AppTextStyles.bodyText2.copyWith(color: AppColor.neutral120),
),
2.height,
//TODO description text not in api.
// Text(
// '${context.translation.date}: ${activity.currentSituation?.date}',
// style: AppTextStyles.bodyText2.copyWith(color: AppColor.neutral120),
// ),
if (activity.activitySparePart?.comment?.isNotEmpty ?? false) ...[
const Divider().defaultStyle(context),
2.height,
@ -245,11 +240,26 @@ class _ActivitiesListViewState extends State<ActivitiesListView> {
],
],
).toShadowContainer(context, padding: 12, showShadow: false).onPress(() {
//TODO write onview detail method..
// Navigator.push(
// context,
// MaterialPageRoute(builder: (context) => WorkOrderDetailsPage(workOrder: activity, serviceRequest: ServiceRequest())),
// );
// if(requestDetailProvider.currentWorkOrder?.data?.status?.id ==3498){
// 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,
// activityStatusId: activity.activityStatus?.id,
// );
// requestDetailProvider.updateSparePartHelperModel(requestDetailProvider.sparePartHelperModel);
// Navigator.of(context).push(MaterialPageRoute(
// builder: (_) => const SparePartRequest(),
// ));
// }
});
}
@ -272,7 +282,7 @@ class _ActivitiesListViewState extends State<ActivitiesListView> {
// backgroundColor: AppColor.getHistoryLogStatusColorByName(activity.activityStatus!.name!),
backgroundColor: AppColor.primary10,
),
"drag_icon".toSvgAsset(height: 12, width: 23, color: AppColor.neutral160),
// "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,
@ -308,7 +318,7 @@ class _ActivitiesListViewState extends State<ActivitiesListView> {
style: AppTextStyles.bodyText2.copyWith(color: AppColor.neutral120),
),
2.height,
if (activity.activityMaintenance?.assignedEmployee != null && activity.activityMaintenance!.assistantEmployees!.isNotEmpty) ...[
if (activity.activityMaintenance?.assistantEmployees != null && activity.activityMaintenance!.assistantEmployees!.isNotEmpty) ...[
Text(
'${context.translation.assistantEmployee}: ${activity.activityMaintenance?.assistantEmployees?.first.user?.userName}',
style: AppTextStyles.bodyText2.copyWith(color: AppColor.neutral120),
@ -329,8 +339,21 @@ class _ActivitiesListViewState extends State<ActivitiesListView> {
style: AppTextStyles.bodyText2.copyWith(color: AppColor.neutral120),
),
],
//need to add all info here...
// if(requestDetailProvider.currentWorkOrder?.data?.status?.id==3498)...[
// const Divider().defaultStyle(context),
// 2.height,
// // Text(
// // activity.activityMaintenance?.technicalComment ?? "",
// // style: AppTextStyles.bodyText2.copyWith(color: AppColor.neutral120),
// // ),
// ]
],
).toShadowContainer(context, padding: 12, showShadow: false);
).toShadowContainer(context, padding: 12, showShadow: false).onPress(() {
if (requestDetailProvider.isReadOnlyRequest) {
onEditMaintenanceRequestPress(context: context, requestDetailProvider: requestDetailProvider, activity: activity);
}
});
}
void onEditMaintenanceRequestPress({required BuildContext context, required ServiceRequestDetailProvider requestDetailProvider, required Activities activity}) async {
@ -391,7 +414,7 @@ class _ActivitiesListViewState extends State<ActivitiesListView> {
}
Navigator.of(context).push(MaterialPageRoute(
builder: (_) => const MaintenanceRequestForm(),
builder: (_) => MaintenanceRequestForm(),
));
}
}

@ -34,6 +34,8 @@ class AssetDetailCard extends StatelessWidget {
textColor: AppColor.white10,
backgroundColor: AppColor.getEquipmentStatusColor(context, requestDetailProvider.engineerUpdateWorkOrderHelperModel!.equipmentStatus!.id ?? 0),
),
//hide if status is closed.
if(!requestDetailProvider.isReadOnlyRequest)
"edit_icon".toSvgAsset(height: 21, width: 21).onPress(() async{
requestDetailProvider.refreshTimer = false;
await Navigator.push(

@ -704,7 +704,7 @@ class ServiceRequestBottomSheet {
);
Navigator.pushReplacement(
context,
MaterialPageRoute(builder: (context) => const MaintenanceRequestForm()),
MaterialPageRoute(builder: (context) => MaintenanceRequestForm()),
);
break;
}

@ -35,12 +35,12 @@ class ServiceRequestDetailView extends StatefulWidget {
}
class _ServiceRequestDetailViewState extends State<ServiceRequestDetailView> {
List<File> _workOrderAttachments = [];
List<AttachmentModel> _workOrderAttachments = [];
@override
void initState() {
ServiceRequestDetailProvider requestDetailProvider = Provider.of<ServiceRequestDetailProvider>(context, listen: false);
_workOrderAttachments = requestDetailProvider.currentWorkOrder?.data?.workOrderAttachments.map((e) => File(e.name ?? '')).toList() ?? [];
_workOrderAttachments = requestDetailProvider.currentWorkOrder?.data?.workOrderAttachments.map((e) => AttachmentModel(e.id??0, File(e.name ?? ''))).toList() ?? [];
super.initState();
}
@ -71,7 +71,7 @@ class _ServiceRequestDetailViewState extends State<ServiceRequestDetailView> {
).expanded,
FooterActionButton.requestDetailsFooterWidget(
workOrderNextStepStatus: requestProvider.currentWorkOrder!.data!.nextStep!.workOrderNextStepEnum!,
// workOrderNextStepStatus: WorkOrderNextStepEnum.eNeedVisit,
status: requestProvider.currentWorkOrder?.data?.status,
isEmpIsAssigned: requestProvider.currentWorkOrder!.data!.assignedEmployee != null,
activities: requestProvider.currentWorkOrder!.data?.activities ?? [],
userProvider: _userProvider,
@ -117,6 +117,15 @@ class _ServiceRequestDetailViewState extends State<ServiceRequestDetailView> {
textColor: AppColor.getHistoryLogStatusTextColorByName(workOrder.status!.name!),
backgroundColor: AppColor.getHistoryLogStatusColorByName(workOrder.status!.name!),
),
if(workOrder.since!=null)...[
8.width,
StatusLabel(
radius: 4,
label:'${workOrder.since} days',
textColor: AppColor.neutral50,
backgroundColor: AppColor.orange80,
),
],
1.width.expanded,
Column(
crossAxisAlignment: CrossAxisAlignment.end,
@ -208,9 +217,18 @@ class _ServiceRequestDetailViewState extends State<ServiceRequestDetailView> {
style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral120),
),
Text(
'Date/Time: ${workOrder.requestedDate!.toString().toServiceRequestDetailsFormat}',
'Requested Date: ${workOrder.requestedDate!.toString().toServiceRequestDetailsFormat}',
style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.neutral120),
),
Text(
'${context.translation.arrivedDate}: ${workOrder.iHaveArrivedDate != null ? workOrder.iHaveArrivedDate.toString().toServiceRequestDetailsFormat : '-'}',
style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.neutral120),
),
Text(
'${context.translation.closedDate}: ${workOrder.closedDate != null ? workOrder.closedDate!.toString().toServiceRequestDetailsFormat : '-'}',
style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.neutral120),
),
const Divider().defaultStyle(context),
//... call response details starts here....
@ -232,13 +250,40 @@ class _ServiceRequestDetailViewState extends State<ServiceRequestDetailView> {
'${context.translation.activityStatus}: ${workOrder.lastActivityStatus?.name ?? "-"}',
style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral120),
),
Text(
'${context.translation.callResponse}: ${workOrder.callResponse ?? "-"}',
style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral120),
),
Text(
'${context.translation.since}: ${workOrder.since != null ? '${workOrder.since} days' : '-'}',
style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral120),
),
8.height,
if (workOrder.rejectReason != null) ...[
const Divider().defaultStyle(context),
8.height,
Text(
context.translation.rejectionDetails,
style: AppTextStyles.heading4.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.neutral50),
),
8.height,
Text(
'${context.translation.rejectionReason}: ${workOrder.rejectReason?.name ?? '-'}',
style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral120),
),
8.height,
Text(
'${context.translation.comment}: ${workOrder.lastComment ?? '-'}',
style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral120),
),
],
8.height,
if ((workOrder.comments ?? "").isNotEmpty) ...[
const Divider().defaultStyle(context),
8.height,
Text(
"Call Comment",
context.translation.callComments,
style: AppTextStyles.heading4.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.neutral50),
),
8.height,
@ -250,14 +295,17 @@ class _ServiceRequestDetailViewState extends State<ServiceRequestDetailView> {
8.height,
const Divider().defaultStyle(context),
MultiFilesPicker(
AttachmentPicker(
label: context.translation.attachments,
files: _workOrderAttachments,
// files: _workOrderAttachments,
attachment: _workOrderAttachments,
buttonColor: AppColor.primary10,
onlyImages: false,
buttonIcon: 'quotation_icon'.toSvgAsset(color: AppColor.primary10),
onChange: (attachment) {
requestProvider.addWorkOrderAttachment(woId: workOrder.requestId!, attachments: attachment);
print('i am called.');
// print('attachment value is ${attachment.last.file?.path}');
// requestProvider.addWorkOrderAttachment(woId: workOrder.requestId!, attachments: _workOrderAttachments);
},
),
@ -373,7 +421,9 @@ class _ServiceRequestDetailViewState extends State<ServiceRequestDetailView> {
}
Widget assetDetailCard({required ServiceRequestDetailProvider requestDetailProvider, required UserProvider userProvider}) {
if (userProvider.user?.type == UsersTypes.engineer && requestDetailProvider.currentWorkOrder?.data?.nextStep!.workOrderNextStepEnum == WorkOrderNextStepEnum.activity) {
print('id i got is ${requestDetailProvider.currentWorkOrder?.data?.status?.id}');
if ((userProvider.user?.type == UsersTypes.engineer && requestDetailProvider.currentWorkOrder?.data?.nextStep!.workOrderNextStepEnum == WorkOrderNextStepEnum.activity) ||
requestDetailProvider.isReadOnlyRequest) {
WorkOrderData currentWorkOrderData = requestDetailProvider.currentWorkOrder!.data!;
requestDetailProvider.engineerUpdateWorkOrderHelperModel = EngineerUpdateWorkOrderHelperModel(
workOrderId: currentWorkOrderData.requestId,

@ -39,6 +39,12 @@ class _AssistantEmployeeCardState extends State<AssistantEmployeeCard> {
Future<void> getInitialData() async {
final user = Provider.of<UserProvider>(context, listen: false).user!;
ServiceRequestDetailProvider requestDetailProvider = Provider.of<ServiceRequestDetailProvider>(context, listen: false);
print('readonly value is ${requestDetailProvider.isReadOnlyRequest}');
if( requestDetailProvider.isReadOnlyRequest){
isExpanded = true;
setState(() {
});
}
isCurrentUserIsAssistantEmp = (user.userID != requestDetailProvider.currentWorkOrder?.data?.assignedEmployee?.userId);
// if (isCurrentUserIsAssistantEmp) {

@ -42,198 +42,198 @@ class _ExternalMaintenanceRequestState extends State<ExternalMaintenanceRequest>
ServiceRequestDetailProvider requestDetailProvider = Provider.of<ServiceRequestDetailProvider>(context, listen: false);
_workingHoursController.text =
requestDetailProvider.activityMaintenanceHelperModel?.supplierWorkingHour != null ? requestDetailProvider.activityMaintenanceHelperModel!.supplierWorkingHour.toString() : '';
}
@override
Widget build(BuildContext context) {
return Consumer<ServiceRequestDetailProvider>(builder: (context, ServiceRequestDetailProvider requestDetailProvider, child) {
return Column(
children: [
Form(
key: _formKey,
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
SingleItemDropDownMenu<SupplierDetails, VendorProvider>(
context: context,
title: context.translation.supplier,
backgroundColor: AppColor.neutral100,
initialValue: requestDetailProvider.activityMaintenanceHelperModel?.supplier,
showAsBottomSheet: true,
onSelect: (supplier) {
if (supplier != null) {
requestDetailProvider.activityMaintenanceHelperModel?.supplier = supplier;
// _subWorkOrders.supplier = supplier;
// log(_subWorkOrders.supplier?.suppPersons?.map((e) => e.personName)?.toString());
setState(() {});
}
},
),
8.height,
Row(
children: [
SingleItemDropDownMenu<SuppPersons, NullableLoadingProvider>(
context: context,
backgroundColor: requestDetailProvider.activityMaintenanceHelperModel?.supplier?.suppliername == null ? AppColor.neutral40 : AppColor.neutral100,
title: context.translation.supplierEngineer,
enabled: requestDetailProvider.activityMaintenanceHelperModel?.supplier?.suppPersons?.isNotEmpty ?? false,
staticData: requestDetailProvider.activityMaintenanceHelperModel?.supplier?.suppPersons,
showAsBottomSheet: true,
initialValue: requestDetailProvider.activityMaintenanceHelperModel?.supEngineer == null
? null
: SuppPersons.fromJson(requestDetailProvider.activityMaintenanceHelperModel?.supEngineer?.toJson()),
onSelect: (suppPerson) {
print(suppPerson?.toJson());
if (suppPerson != null) {
requestDetailProvider.activityMaintenanceHelperModel?.supEngineer = SuppEngineerWorkOrders.fromJson(suppPerson.toJson());
requestDetailProvider.updateActivityMaintenanceHelperModel(requestDetailProvider.activityMaintenanceHelperModel);
// engineer = SuppEngineerWorkOrders(
// id: suppPerson?.supplierId,
// supplierContactId: suppPerson?.id,
// personName: suppPerson?.personName,
// contact: suppPerson?.contact,
// externalEngCode: suppPerson?.externalEngCode,
// email: suppPerson?.email,
// );
setState(() {});
}
},
).expanded,
8.width,
Container(
height: 56.toScreenHeight,
width: 60.toScreenWidth,
decoration: BoxDecoration(
color: requestDetailProvider.activityMaintenanceHelperModel?.supplier?.suppliername == null ? AppColor.neutral40 : AppColor.neutral100,
borderRadius: BorderRadius.circular(10),
boxShadow: [BoxShadow(color: Colors.black.withOpacity(0.05), blurRadius: 10)],
),
child: Icon(
Icons.add,
color: context.isDark ? null : AppColor.neutral60,
),
).onPress(requestDetailProvider.activityMaintenanceHelperModel?.supplier?.suppliername == null
? null
: () async {
SuppEngineerWorkOrders suppEngineer = (await showModalBottomSheet(
context: context,
useSafeArea: true,
isScrollControlled: true,
backgroundColor: Colors.transparent,
builder: (context) => AddSupplierEngineerBottomSheet(requestDetailProvider.activityMaintenanceHelperModel!.supplier!.id!.toInt()),
)) as SuppEngineerWorkOrders;
requestDetailProvider.activityMaintenanceHelperModel?.supplier?.suppPersons ??= [];
requestDetailProvider.activityMaintenanceHelperModel?.supplier?.suppPersons?.add(SuppPersons.fromJson(suppEngineer.toJson()));
requestDetailProvider.activityMaintenanceHelperModel?.supEngineer = suppEngineer;
setState(() {});
}),
],
),
8.height,
Row(
mainAxisSize: MainAxisSize.min,
children: [
ADatePicker(
label: context.translation.startTime,
hideShadow: true,
backgroundColor: AppColor.neutral100,
date: requestDetailProvider.activityMaintenanceHelperModel?.supplierStartTime,
formatDateWithTime: true,
onDatePicker: (selectedDate) {
showTimePicker(
context: context,
initialTime: TimeOfDay.now(),
).then((selectedTime) {
// Handle the selected date and time here.
if (selectedTime != null) {
DateTime selectedDateTime = DateTime(
selectedDate.year,
selectedDate.month,
selectedDate.day,
selectedTime.hour,
selectedTime.minute,
);
requestDetailProvider.activityMaintenanceHelperModel?.supplierStartTime = selectedDateTime;
requestDetailProvider.activityMaintenanceHelperModel?.supplierEndTime = null;
return IgnorePointer(
ignoring: requestDetailProvider.isReadOnlyRequest,
child: Column(
children: [
Form(
key: _formKey,
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
SingleItemDropDownMenu<SupplierDetails, VendorProvider>(
context: context,
title: context.translation.supplier,
backgroundColor: AppColor.neutral100,
initialValue: requestDetailProvider.activityMaintenanceHelperModel?.supplier,
showAsBottomSheet: true,
onSelect: (supplier) {
if (supplier != null) {
requestDetailProvider.activityMaintenanceHelperModel?.supplier = supplier;
// _subWorkOrders.supplier = supplier;
// log(_subWorkOrders.supplier?.suppPersons?.map((e) => e.personName)?.toString());
setState(() {});
}
},
),
8.height,
Row(
children: [
SingleItemDropDownMenu<SuppPersons, NullableLoadingProvider>(
context: context,
backgroundColor: requestDetailProvider.activityMaintenanceHelperModel?.supplier?.suppliername == null ? AppColor.neutral40 : AppColor.neutral100,
title: context.translation.supplierEngineer,
enabled: requestDetailProvider.activityMaintenanceHelperModel?.supplier?.suppPersons?.isNotEmpty ?? false,
staticData: requestDetailProvider.activityMaintenanceHelperModel?.supplier?.suppPersons,
showAsBottomSheet: true,
initialValue: requestDetailProvider.activityMaintenanceHelperModel?.supEngineer == null
? null
: SuppPersons.fromJson(requestDetailProvider.activityMaintenanceHelperModel?.supEngineer?.toJson()),
onSelect: (suppPerson) {
print(suppPerson?.toJson());
if (suppPerson != null) {
requestDetailProvider.activityMaintenanceHelperModel?.supEngineer = SuppEngineerWorkOrders.fromJson(suppPerson.toJson());
requestDetailProvider.updateActivityMaintenanceHelperModel(requestDetailProvider.activityMaintenanceHelperModel);
_workingHoursController.clear();
ServiceRequestUtils.calculateAndAssignWorkingHours(
startTime: requestDetailProvider.activityMaintenanceHelperModel!.supplierStartTime,
endTime: requestDetailProvider.activityMaintenanceHelperModel!.endTime,
workingHoursController: _workingHoursController,
updateModel: (hours) {
requestDetailProvider.activityMaintenanceHelperModel?.supplierWorkingHour = hours;
},
);
// engineer = SuppEngineerWorkOrders(
// id: suppPerson?.supplierId,
// supplierContactId: suppPerson?.id,
// personName: suppPerson?.personName,
// contact: suppPerson?.contact,
// externalEngCode: suppPerson?.externalEngCode,
// email: suppPerson?.email,
// );
setState(() {});
}
});
},
).expanded,
8.width,
ADatePicker(
label: context.translation.endTime,
hideShadow: true,
backgroundColor: AppColor.neutral100,
date: requestDetailProvider.activityMaintenanceHelperModel?.supplierEndTime,
formatDateWithTime: true,
onDatePicker: (selectedDate) {
showTimePicker(
context: context,
initialTime: TimeOfDay.now(),
).then((selectedTime) {
// Handle the selected date and time here.
if (selectedTime != null) {
DateTime selectedDateTime = DateTime(
selectedDate.year,
selectedDate.month,
selectedDate.day,
selectedTime.hour,
selectedTime.minute,
);
if (requestDetailProvider.activityMaintenanceHelperModel!.supplierStartTime != null &&
selectedDateTime.isBefore(requestDetailProvider.activityMaintenanceHelperModel!.supplierStartTime!)) {
"End Date time must be greater then start date".showToast;
return;
},
).expanded,
8.width,
Container(
height: 56.toScreenHeight,
width: 60.toScreenWidth,
decoration: BoxDecoration(
color: requestDetailProvider.activityMaintenanceHelperModel?.supplier?.suppliername == null ? AppColor.neutral40 : AppColor.neutral100,
borderRadius: BorderRadius.circular(10),
boxShadow: [BoxShadow(color: Colors.black.withOpacity(0.05), blurRadius: 10)],
),
child: Icon(
Icons.add,
color: context.isDark ? null : AppColor.neutral60,
),
).onPress(requestDetailProvider.activityMaintenanceHelperModel?.supplier?.suppliername == null
? null
: () async {
SuppEngineerWorkOrders suppEngineer = (await showModalBottomSheet(
context: context,
useSafeArea: true,
isScrollControlled: true,
backgroundColor: Colors.transparent,
builder: (context) => AddSupplierEngineerBottomSheet(requestDetailProvider.activityMaintenanceHelperModel!.supplier!.id!.toInt()),
)) as SuppEngineerWorkOrders;
requestDetailProvider.activityMaintenanceHelperModel?.supplier?.suppPersons ??= [];
requestDetailProvider.activityMaintenanceHelperModel?.supplier?.suppPersons?.add(SuppPersons.fromJson(suppEngineer.toJson()));
requestDetailProvider.activityMaintenanceHelperModel?.supEngineer = suppEngineer;
setState(() {});
}),
],
),
8.height,
Row(
mainAxisSize: MainAxisSize.min,
children: [
ADatePicker(
label: context.translation.startTime,
hideShadow: true,
backgroundColor: AppColor.neutral100,
date: requestDetailProvider.activityMaintenanceHelperModel?.supplierStartTime,
formatDateWithTime: true,
onDatePicker: (selectedDate) {
showTimePicker(
context: context,
initialTime: TimeOfDay.now(),
).then((selectedTime) {
// Handle the selected date and time here.
if (selectedTime != null) {
DateTime selectedDateTime = DateTime(
selectedDate.year,
selectedDate.month,
selectedDate.day,
selectedTime.hour,
selectedTime.minute,
);
requestDetailProvider.activityMaintenanceHelperModel?.supplierStartTime = selectedDateTime;
requestDetailProvider.activityMaintenanceHelperModel?.supplierEndTime = null;
requestDetailProvider.updateActivityMaintenanceHelperModel(requestDetailProvider.activityMaintenanceHelperModel);
_workingHoursController.clear();
ServiceRequestUtils.calculateAndAssignWorkingHours(
startTime: requestDetailProvider.activityMaintenanceHelperModel!.supplierStartTime,
endTime: requestDetailProvider.activityMaintenanceHelperModel!.endTime,
workingHoursController: _workingHoursController,
updateModel: (hours) {
requestDetailProvider.activityMaintenanceHelperModel?.supplierWorkingHour = hours;
},
);
}
requestDetailProvider.activityMaintenanceHelperModel?.supplierEndTime = selectedDateTime;
requestDetailProvider.updateActivityMaintenanceHelperModel(requestDetailProvider.activityMaintenanceHelperModel);
ServiceRequestUtils.calculateAndAssignWorkingHours(
startTime: requestDetailProvider.activityMaintenanceHelperModel!.supplierStartTime,
endTime: requestDetailProvider.activityMaintenanceHelperModel!.supplierEndTime,
workingHoursController: _workingHoursController,
updateModel: (hours) {
requestDetailProvider.activityMaintenanceHelperModel?.supplierWorkingHour = hours;
},
);
}
});
},
).expanded,
],
),
8.height,
AppTextFormField(
labelText: context.translation.workingHours,
backgroundColor: AppColor.neutral80,
controller: _workingHoursController,
suffixIcon: "clock".toSvgAsset(width: 20, color: context.isDark ? AppColor.neutral10 : null).paddingOnly(end: 16),
initialValue:
requestDetailProvider.activityMaintenanceHelperModel?.supplierWorkingHour != null ? requestDetailProvider.activityMaintenanceHelperModel?.supplierWorkingHour.toString() : '',
textAlign: TextAlign.center,
labelStyle: AppTextStyles.textFieldLabelStyle,
enable: false,
showShadow: false,
style: Theme.of(context).textTheme.titleMedium,
),
8.height,
],
),
).toShadowContainer(context).paddingOnly(start: 16, end: 16, top: 12),
],
});
},
).expanded,
8.width,
ADatePicker(
label: context.translation.endTime,
hideShadow: true,
backgroundColor: AppColor.neutral100,
date: requestDetailProvider.activityMaintenanceHelperModel?.supplierEndTime,
formatDateWithTime: true,
onDatePicker: (selectedDate) {
showTimePicker(
context: context,
initialTime: TimeOfDay.now(),
).then((selectedTime) {
// Handle the selected date and time here.
if (selectedTime != null) {
DateTime selectedDateTime = DateTime(
selectedDate.year,
selectedDate.month,
selectedDate.day,
selectedTime.hour,
selectedTime.minute,
);
if (requestDetailProvider.activityMaintenanceHelperModel!.supplierStartTime != null &&
selectedDateTime.isBefore(requestDetailProvider.activityMaintenanceHelperModel!.supplierStartTime!)) {
"End Date time must be greater then start date".showToast;
return;
}
requestDetailProvider.activityMaintenanceHelperModel?.supplierEndTime = selectedDateTime;
requestDetailProvider.updateActivityMaintenanceHelperModel(requestDetailProvider.activityMaintenanceHelperModel);
ServiceRequestUtils.calculateAndAssignWorkingHours(
startTime: requestDetailProvider.activityMaintenanceHelperModel!.supplierStartTime,
endTime: requestDetailProvider.activityMaintenanceHelperModel!.supplierEndTime,
workingHoursController: _workingHoursController,
updateModel: (hours) {
requestDetailProvider.activityMaintenanceHelperModel?.supplierWorkingHour = hours;
},
);
}
});
},
).expanded,
],
),
8.height,
AppTextFormField(
labelText: context.translation.workingHours,
backgroundColor: AppColor.neutral80,
controller: _workingHoursController,
suffixIcon: "clock".toSvgAsset(width: 20, color: context.isDark ? AppColor.neutral10 : null).paddingOnly(end: 16),
initialValue:
requestDetailProvider.activityMaintenanceHelperModel?.supplierWorkingHour != null ? requestDetailProvider.activityMaintenanceHelperModel?.supplierWorkingHour.toString() : '',
textAlign: TextAlign.center,
labelStyle: AppTextStyles.textFieldLabelStyle,
enable: false,
showShadow: false,
style: Theme.of(context).textTheme.titleMedium,
),
8.height,
],
),
).toShadowContainer(context).paddingOnly(start: 16, end: 16, top: 12),
],
),
);
});
}
}

@ -35,14 +35,11 @@ class _InternalMaintenanceRequestState extends State<InternalMaintenanceRequest>
Lookup statusLookup = Lookup.fromJson({"id": 5619, "name": "New", "value": 1});
@override
void initState() {
_requestDetailProvider = Provider.of<ServiceRequestDetailProvider>(context, listen: false);
super.initState();
WidgetsBinding.instance.addPostFrameCallback((_) {
//need to confirm with backend api data...
// _deviceImages.addAll(_serviceRequest.devicePhotos!.map((e) => File(e)).toList());
_travellingHoursController.text =
_requestDetailProvider?.activityMaintenanceHelperModel?.travelHours != null ? _requestDetailProvider!.activityMaintenanceHelperModel!.travelHours.toString() : '';
});
@ -59,8 +56,6 @@ class _InternalMaintenanceRequestState extends State<InternalMaintenanceRequest>
@override
Widget build(BuildContext context) {
return Consumer<ServiceRequestDetailProvider>(builder: (context, requestDetailProvider, child) {
double totalWorkingHours = _requestDetailProvider?.activityMaintenanceHelperModel?.activityMaintenanceTimers
?.fold(0.0, (sum, item) => (sum ?? 0) + DateTime.parse(item.endTime!).difference(DateTime.parse(item.startTime!)).inSeconds) ??
0;
@ -70,229 +65,231 @@ class _InternalMaintenanceRequestState extends State<InternalMaintenanceRequest>
: requestDetailProvider.activityMaintenanceHelperModel?.id == requestDetailProvider.lastVisitedRequestActivityId;
return SingleChildScrollView(
child: Column(
children: [
Form(
key: _formKey,
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
// SingleItemDropDownMenu<Lookup, ActivityStatusProvider>(
// context: context,
// height: 56.toScreenHeight,
// title: context.translation.activityStatus,
// showShadow: false,
// backgroundColor: AppColor.neutral100,
// initialValue: requestDetailProvider.activityMaintenanceHelperModel?.activityStatus,
// onSelect: (status) {
// print('status i got is ${status?.toJson()}');
// requestDetailProvider.activityMaintenanceHelperModel?.activityStatus = status;
// },
// ),
// 8.height,
SingleItemDropDownMenu<Lookup, LastSituationProvider>(
context: context,
height: 56.toScreenHeight,
title: context.translation.activityStatus,
showShadow: false,
backgroundColor: AppColor.neutral100,
showAsBottomSheet: true,
initialValue: requestDetailProvider.activityMaintenanceHelperModel?.activityStatus,
onSelect: (status) {
if (status != null) {
requestDetailProvider.activityMaintenanceHelperModel?.activityStatus = status;
setState(() {});
}
},
),
8.height,
AppTimer(
label: context.translation.timer,
timer: requestDetailProvider.activityMaintenanceHelperModel?.activityMaintenanceTimerModel,
enabled: enableTimer,
timerProgress: (isRunning) {
print("timerProgress:$isRunning");
},
onChange: (timer) async {
requestDetailProvider.activityMaintenanceHelperModel?.activityMaintenanceTimerModel = timer;
if (timer.startAt != null && timer.endAt != null) {
requestDetailProvider.activityMaintenanceHelperModel?.timerModelList = requestDetailProvider.activityMaintenanceHelperModel?.timerModelList ?? [];
requestDetailProvider.activityMaintenanceHelperModel?.timerModelList!.add(timer);
}
return true;
},
),
// Row(
// mainAxisSize: MainAxisSize.min,
// children: [
// ADatePicker(
// label: context.translation.startTime,
// hideShadow: true,
// backgroundColor: AppColor.neutral100,
// date: requestDetailProvider.activityMaintenanceHelperModel?.startTime,
// formatDateWithTime: true,
// onDatePicker: (selectedDate) {
// showTimePicker(
// context: context,
// initialTime: TimeOfDay.now(),
// ).then((selectedTime) {
// // Handle the selected date and time here.
// if (selectedTime != null) {
// DateTime selectedDateTime = DateTime(
// selectedDate.year,
// selectedDate.month,
// selectedDate.day,
// selectedTime.hour,
// selectedTime.minute,
// );
// requestDetailProvider.activityMaintenanceHelperModel?.startTime = selectedDateTime;
// requestDetailProvider.activityMaintenanceHelperModel?.endTime = null;
// requestDetailProvider.updateActivityMaintenanceHelperModel(requestDetailProvider.activityMaintenanceHelperModel);
// _workingHoursController.clear();
// ServiceRequestUtils.calculateAndAssignWorkingHours(
// startTime: requestDetailProvider.activityMaintenanceHelperModel!.startTime,
// endTime: requestDetailProvider.activityMaintenanceHelperModel!.endTime,
// workingHoursController: _workingHoursController,
// updateModel: (hours) {
// requestDetailProvider.activityMaintenanceHelperModel?.workingHour = hours;
// },
// );
// }
// });
// },
// ).expanded,
// 8.width,
// ADatePicker(
// label: context.translation.endTime,
// hideShadow: true,
// backgroundColor: AppColor.neutral100,
// date: requestDetailProvider.activityMaintenanceHelperModel?.endTime,
// formatDateWithTime: true,
// onDatePicker: (selectedDate) {
// showTimePicker(
// context: context,
// initialTime: TimeOfDay.now(),
// ).then((selectedTime) {
// // Handle the selected date and time here.
// if (selectedTime != null) {
// DateTime selectedDateTime = DateTime(selectedDate.year, selectedDate.month, selectedDate.day, selectedTime.hour, selectedTime.minute);
// if (requestDetailProvider.activityMaintenanceHelperModel!.startTime != null &&
// selectedDateTime.isBefore(requestDetailProvider.activityMaintenanceHelperModel!.startTime!)) {
// "End Date time must be greater then start date".showToast;
// return;
// }
// requestDetailProvider.activityMaintenanceHelperModel?.endTime = selectedDateTime;
// requestDetailProvider.updateActivityMaintenanceHelperModel(requestDetailProvider.activityMaintenanceHelperModel);
// ServiceRequestUtils.calculateAndAssignWorkingHours(
// startTime: requestDetailProvider.activityMaintenanceHelperModel!.startTime,
// endTime: requestDetailProvider.activityMaintenanceHelperModel!.endTime,
// workingHoursController: _workingHoursController,
// updateModel: (hours) {
// requestDetailProvider.activityMaintenanceHelperModel?.workingHour = hours;
// },
// );
// }
// });
// },
// ).expanded,
// ],
// ),
8.height,
if (totalWorkingHours > 0.0) ...[
Container(
child: IgnorePointer(
ignoring: _requestDetailProvider!.isReadOnlyRequest,
child: Column(
children: [
Form(
key: _formKey,
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
// SingleItemDropDownMenu<Lookup, ActivityStatusProvider>(
// context: context,
// height: 56.toScreenHeight,
// title: context.translation.activityStatus,
// showShadow: false,
// backgroundColor: AppColor.neutral100,
// initialValue: requestDetailProvider.activityMaintenanceHelperModel?.activityStatus,
// onSelect: (status) {
// print('status i got is ${status?.toJson()}');
// requestDetailProvider.activityMaintenanceHelperModel?.activityStatus = status;
// },
// ),
// 8.height,
SingleItemDropDownMenu<Lookup, LastSituationProvider>(
context: context,
height: 56.toScreenHeight,
padding: EdgeInsets.symmetric(horizontal: 16.toScreenWidth),
alignment: Alignment.centerLeft,
decoration: BoxDecoration(
color: context.isDark ? AppColor.neutral40 : AppColor.background(context),
borderRadius: BorderRadius.circular(10),
boxShadow: [BoxShadow(color: Colors.black.withOpacity(0.05), blurRadius: 10)],
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
"Total Working Time",
style: Theme.of(context).textTheme.bodySmall?.copyWith(color: context.isDark ? null : AppColor.neutral20, fontWeight: FontWeight.w500),
),
Text(
" ${ServiceRequestUtils.formatTimerDuration(totalWorkingHours.round())}",
style: Theme.of(context).textTheme.bodyMedium,
),
],
title: context.translation.activityStatus,
showShadow: false,
backgroundColor: AppColor.neutral100,
showAsBottomSheet: true,
initialValue: requestDetailProvider.activityMaintenanceHelperModel?.activityStatus,
onSelect: (status) {
if (status != null) {
requestDetailProvider.activityMaintenanceHelperModel?.activityStatus = status;
setState(() {});
}
},
),
8.height,
AppTimer(
label: context.translation.timer,
timer: requestDetailProvider.activityMaintenanceHelperModel?.activityMaintenanceTimerModel,
enabled: enableTimer,
timerProgress: (isRunning) {
print("timerProgress:$isRunning");
},
onChange: (timer) async {
requestDetailProvider.activityMaintenanceHelperModel?.activityMaintenanceTimerModel = timer;
if (timer.startAt != null && timer.endAt != null) {
requestDetailProvider.activityMaintenanceHelperModel?.timerModelList = requestDetailProvider.activityMaintenanceHelperModel?.timerModelList ?? [];
requestDetailProvider.activityMaintenanceHelperModel?.timerModelList!.add(timer);
}
return true;
},
),
// Row(
// mainAxisSize: MainAxisSize.min,
// children: [
// ADatePicker(
// label: context.translation.startTime,
// hideShadow: true,
// backgroundColor: AppColor.neutral100,
// date: requestDetailProvider.activityMaintenanceHelperModel?.startTime,
// formatDateWithTime: true,
// onDatePicker: (selectedDate) {
// showTimePicker(
// context: context,
// initialTime: TimeOfDay.now(),
// ).then((selectedTime) {
// // Handle the selected date and time here.
// if (selectedTime != null) {
// DateTime selectedDateTime = DateTime(
// selectedDate.year,
// selectedDate.month,
// selectedDate.day,
// selectedTime.hour,
// selectedTime.minute,
// );
// requestDetailProvider.activityMaintenanceHelperModel?.startTime = selectedDateTime;
// requestDetailProvider.activityMaintenanceHelperModel?.endTime = null;
// requestDetailProvider.updateActivityMaintenanceHelperModel(requestDetailProvider.activityMaintenanceHelperModel);
// _workingHoursController.clear();
// ServiceRequestUtils.calculateAndAssignWorkingHours(
// startTime: requestDetailProvider.activityMaintenanceHelperModel!.startTime,
// endTime: requestDetailProvider.activityMaintenanceHelperModel!.endTime,
// workingHoursController: _workingHoursController,
// updateModel: (hours) {
// requestDetailProvider.activityMaintenanceHelperModel?.workingHour = hours;
// },
// );
// }
// });
// },
// ).expanded,
// 8.width,
// ADatePicker(
// label: context.translation.endTime,
// hideShadow: true,
// backgroundColor: AppColor.neutral100,
// date: requestDetailProvider.activityMaintenanceHelperModel?.endTime,
// formatDateWithTime: true,
// onDatePicker: (selectedDate) {
// showTimePicker(
// context: context,
// initialTime: TimeOfDay.now(),
// ).then((selectedTime) {
// // Handle the selected date and time here.
// if (selectedTime != null) {
// DateTime selectedDateTime = DateTime(selectedDate.year, selectedDate.month, selectedDate.day, selectedTime.hour, selectedTime.minute);
// if (requestDetailProvider.activityMaintenanceHelperModel!.startTime != null &&
// selectedDateTime.isBefore(requestDetailProvider.activityMaintenanceHelperModel!.startTime!)) {
// "End Date time must be greater then start date".showToast;
// return;
// }
// requestDetailProvider.activityMaintenanceHelperModel?.endTime = selectedDateTime;
// requestDetailProvider.updateActivityMaintenanceHelperModel(requestDetailProvider.activityMaintenanceHelperModel);
// ServiceRequestUtils.calculateAndAssignWorkingHours(
// startTime: requestDetailProvider.activityMaintenanceHelperModel!.startTime,
// endTime: requestDetailProvider.activityMaintenanceHelperModel!.endTime,
// workingHoursController: _workingHoursController,
// updateModel: (hours) {
// requestDetailProvider.activityMaintenanceHelperModel?.workingHour = hours;
// },
// );
// }
// });
// },
// ).expanded,
// ],
// ),
8.height,
if (totalWorkingHours > 0.0) ...[
Container(
height: 56.toScreenHeight,
padding: EdgeInsets.symmetric(horizontal: 16.toScreenWidth),
alignment: Alignment.centerLeft,
decoration: BoxDecoration(
color: context.isDark ? AppColor.neutral40 : AppColor.background(context),
borderRadius: BorderRadius.circular(10),
boxShadow: [BoxShadow(color: Colors.black.withOpacity(0.05), blurRadius: 10)],
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
"Total Working Time",
style: Theme.of(context).textTheme.bodySmall?.copyWith(color: context.isDark ? null : AppColor.neutral20, fontWeight: FontWeight.w500),
),
Text(
" ${ServiceRequestUtils.formatTimerDuration(totalWorkingHours.round())}",
style: Theme.of(context).textTheme.bodyMedium,
),
],
),
),
8.height,
],
// if (totalWorkingHours > 0.0) ...[
// AppTextFormField(
// labelText: context.translation.workingHours,
// backgroundColor: AppColor.neutral80,
// controller: _workingHoursController,
// suffixIcon: "clock".toSvgAsset(width: 20, color: context.isDark ? AppColor.neutral10 : null).paddingOnly(end: 16),
// initialValue: requestDetailProvider.activityMaintenanceHelperModel?.workingHour != null ? requestDetailProvider.activityMaintenanceHelperModel?.workingHour.toString() : '',
// textAlign: TextAlign.center,
// labelStyle: AppTextStyles.textFieldLabelStyle,
// enable: false,
// showShadow: false,
// style: Theme.of(context).textTheme.titleMedium,
// ),
// 8.height,
// ],
AppTextFormField(
labelText: context.translation.travelingHours,
controller: _travellingHoursController,
backgroundColor: AppColor.neutral100,
showShadow: false,
labelStyle: AppTextStyles.textFieldLabelStyle,
suffixIcon: "clock".toSvgAsset(width: 20, color: context.isDark ? AppColor.neutral10 : null).paddingOnly(end: 16),
initialValue: requestDetailProvider.activityMaintenanceHelperModel?.travelHours?.toString(),
textInputType: TextInputType.number,
onChange: (value) {
requestDetailProvider.activityMaintenanceHelperModel?.travelHours = num.parse(value); // int.tryParse(value);
},
// contentPadding: EdgeInsets.symmetric(vertical: 18.toScreenHeight, horizontal: 16.toScreenWidth),
onSaved: (value) {
requestDetailProvider.activityMaintenanceHelperModel?.travelHours = value as num?;
},
),
16.height,
repairLocationWidget(context, requestDetailProvider),
16.height,
AppTextFormField(
labelText: context.translation.assignedEmployee,
backgroundColor: AppColor.neutral80,
initialValue: requestDetailProvider.activityMaintenanceHelperModel?.assignedEmployee?.userName,
textAlign: TextAlign.center,
labelStyle: AppTextStyles.textFieldLabelStyle,
showShadow: false,
enable: false,
style: Theme.of(context).textTheme.titleMedium,
),
8.height,
AppTextFormField(
initialValue: requestDetailProvider.activityMaintenanceHelperModel?.technicalComment,
labelText: context.translation.technicalComment,
backgroundColor: AppColor.neutral100,
showShadow: false,
labelStyle: AppTextStyles.textFieldLabelStyle,
alignLabelWithHint: true,
textInputType: TextInputType.multiline,
onChange: (value) {
requestDetailProvider.activityMaintenanceHelperModel?.technicalComment = value;
},
onSaved: (value) {
requestDetailProvider.activityMaintenanceHelperModel?.technicalComment = value;
},
),
],
// if (totalWorkingHours > 0.0) ...[
// AppTextFormField(
// labelText: context.translation.workingHours,
// backgroundColor: AppColor.neutral80,
// controller: _workingHoursController,
// suffixIcon: "clock".toSvgAsset(width: 20, color: context.isDark ? AppColor.neutral10 : null).paddingOnly(end: 16),
// initialValue: requestDetailProvider.activityMaintenanceHelperModel?.workingHour != null ? requestDetailProvider.activityMaintenanceHelperModel?.workingHour.toString() : '',
// textAlign: TextAlign.center,
// labelStyle: AppTextStyles.textFieldLabelStyle,
// enable: false,
// showShadow: false,
// style: Theme.of(context).textTheme.titleMedium,
// ),
// 8.height,
// ],
AppTextFormField(
labelText: context.translation.travelingHours,
controller: _travellingHoursController,
backgroundColor: AppColor.neutral100,
showShadow: false,
labelStyle: AppTextStyles.textFieldLabelStyle,
suffixIcon: "clock".toSvgAsset(width: 20, color: context.isDark ? AppColor.neutral10 : null).paddingOnly(end: 16),
initialValue: requestDetailProvider.activityMaintenanceHelperModel?.travelHours?.toString(),
textInputType: TextInputType.number,
onChange: (value) {
requestDetailProvider.activityMaintenanceHelperModel?.travelHours = num.parse(value) ;// int.tryParse(value);
},
// contentPadding: EdgeInsets.symmetric(vertical: 18.toScreenHeight, horizontal: 16.toScreenWidth),
onSaved: (value) {
requestDetailProvider.activityMaintenanceHelperModel?.travelHours = value as num?;
},
),
16.height,
repairLocationWidget(context, requestDetailProvider),
16.height,
AppTextFormField(
labelText: context.translation.assignedEmployee,
backgroundColor: AppColor.neutral80,
initialValue: requestDetailProvider.activityMaintenanceHelperModel?.assignedEmployee?.userName,
textAlign: TextAlign.center,
labelStyle: AppTextStyles.textFieldLabelStyle,
showShadow: false,
enable: false,
style: Theme.of(context).textTheme.titleMedium,
),
8.height,
AppTextFormField(
initialValue: requestDetailProvider.activityMaintenanceHelperModel?.technicalComment,
labelText: context.translation.technicalComment,
backgroundColor: AppColor.neutral100,
showShadow: false,
labelStyle: AppTextStyles.textFieldLabelStyle,
alignLabelWithHint: true,
textInputType: TextInputType.multiline,
onChange: (value) {
requestDetailProvider.activityMaintenanceHelperModel?.technicalComment = value;
},
onSaved: (value) {
requestDetailProvider.activityMaintenanceHelperModel?.technicalComment = value;
},
),
],
),
).toShadowContainer(context).paddingOnly(start: 13, end: 14, top: 12),
const AssistantEmployeeCard().toShadowContainer(context, paddingObject: const EdgeInsets.symmetric(horizontal: 16)).paddingOnly(start: 13, end: 14, top: 12),
100.height,
],
),
).toShadowContainer(context).paddingOnly(start: 13, end: 14, top: 12),
const AssistantEmployeeCard().toShadowContainer(context, paddingObject: const EdgeInsets.symmetric(horizontal: 16)).paddingOnly(start: 13, end: 14, top: 12),
100.height,
],
),
),
);
});

@ -18,7 +18,7 @@ import 'package:test_sa/service_request_latest/views/forms/maintenance_request/c
import 'package:test_sa/service_request_latest/views/forms/maintenance_request/components/internal_request.dart';
class MaintenanceRequestForm extends StatefulWidget {
const MaintenanceRequestForm({Key? key}) : super(key: key);
MaintenanceRequestForm({Key? key}) : super(key: key);
@override
_MaintenanceRequestFormState createState() => _MaintenanceRequestFormState();

@ -148,7 +148,7 @@ class _SparePartRequestState extends State<SparePartRequest> with TickerProvider
12.height,
SingleItemDropDownMenu<SparePart, NullableLoadingProvider>(
context: context,
title: context.translation.partNo,
title: context.translation.part,
staticData: _spareParts,
showShadow: false,
showAsBottomSheet: true,

@ -57,11 +57,13 @@ class _RoomInspectionCardState extends State<RoomInspectionCard> {
required PlanRecurrentMedicalTaskRoomTabAttributes model,
required BuildContext context,
}) {
bool status = model.attribute != null
? model.attributeValue == 'true'
? true
: false
: false;
bool status = (model.attribute == null || model.attributeValue == null)
? true
: model.attribute != null
? model.attributeValue == 'true'
? true
: false
: false;
return Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
@ -71,7 +73,7 @@ class _RoomInspectionCardState extends State<RoomInspectionCard> {
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
model.attribute!.name!,
model.attribute?.name ?? '',
overflow: TextOverflow.ellipsis,
maxLines: 1,
style: AppTextStyles.bodyText2.copyWith(color: AppColor.white936),

@ -11,6 +11,7 @@ import 'package:test_sa/models/ppm/ppm.dart';
import 'package:test_sa/models/ppm/recurrent_wo.dart';
import 'package:test_sa/models/timer_model.dart';
import 'package:test_sa/new_views/app_style/app_color.dart';
import 'package:test_sa/new_views/common_widgets/app_text_form_field.dart';
import 'package:test_sa/service_request_latest/utilities/service_request_utils.dart';
import 'package:test_sa/views/widgets/requests/request_status.dart';
import 'package:test_sa/views/widgets/timer/app_timer.dart';
@ -56,11 +57,15 @@ class RecurrentTaskInfoWidget extends StatelessWidget {
8.height,
buildingInfoWidget(label: context.translation.room, value: model?.room?.name?.cleanupWhitespace.capitalizeFirstOfEach, context: context),
8.height,
_timerWidget(context, model!.totalWorkingHours!)
_timerWidget(context, model!.totalWorkingHours!),
8.height,
_commentWidget(context: context, model: model)
],
// ],
).toShadowContainer(context, padding: 12)
: _timerWidget(context, model!.totalWorkingHours!).toShadowContainer(context, padding: 12),
: Column(
children: [_timerWidget(context, model!.totalWorkingHours!).toShadowContainer(context, padding: 12), 8.height, _commentWidget(context: context, model: model)],
),
],
);
}
@ -104,6 +109,24 @@ class RecurrentTaskInfoWidget extends StatelessWidget {
);
});
}
Widget _commentWidget({RecurrentWoData? model, required BuildContext context}) {
return AppTextFormField(
initialValue: model?.comment,
labelText: context.translation.comment,
backgroundColor: AppColor.neutral100,
showShadow: false,
labelStyle: AppTextStyles.textFieldLabelStyle,
alignLabelWithHint: true,
textInputType: TextInputType.multiline,
onChange: (value) {
model?.comment = value;
},
onSaved: (value) {
model?.comment = value;
},
);
}
}
Widget buildingInfoWidget({required String label, required String? value, required BuildContext context}) {
@ -118,10 +141,9 @@ Widget buildingInfoWidget({required String label, required String? value, requir
),
3.height,
Text(
value??'',
value ?? '',
style: AppTextStyles.bodyText2.copyWith(color: AppColor.black10),
)
],
).toShadowContainer(context, backgroundColor: AppColor.neutral100, borderRadius: 10, paddingObject: EdgeInsets.all(12.toScreenHeight), showShadow: false);
}

@ -72,25 +72,27 @@ class _RecurrentWorkOrderViewState extends State<RecurrentWorkOrderView> {
],
).paddingAll(12),
).paddingOnly(bottom: 85),
FooterActionButton.footerContainer(
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
AppFilledButton(
label: context.translation.save,
buttonColor: AppColor.white60,
textColor: AppColor.black10,
onPressed: () => _updateTask(context: context, status: 0),
).expanded,
12.width,
AppFilledButton(
label: context.translation.complete,
buttonColor: AppColor.primary10,
onPressed: () => _updateTask(context: context, status: 1),
).expanded,
],
if (requestProvider.recurrentWoData?.status?.id != 270) ...[
FooterActionButton.footerContainer(
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
AppFilledButton(
label: context.translation.save,
buttonColor: AppColor.white60,
textColor: AppColor.black10,
onPressed: () => _updateTask(context: context, status: 0),
).expanded,
12.width,
AppFilledButton(
label: context.translation.complete,
buttonColor: AppColor.primary10,
onPressed: () => _updateTask(context: context, status: 1),
).expanded,
],
),
),
),
]
],
)
: NoDataFound(message: context.translation.noDataFound).center,

@ -8,6 +8,7 @@ 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/device/asset.dart';
import 'package:test_sa/models/lookup.dart';
import 'package:test_sa/models/plan_preventive_visit/plan_preventive_visit_model.dart';
import 'package:test_sa/new_views/common_widgets/app_filled_button.dart';

@ -15,9 +15,11 @@ import 'package:test_sa/providers/ppm_electrical_safety_provider.dart';
import 'package:test_sa/providers/ppm_service_provider.dart';
import 'package:test_sa/providers/ppm_task_status_provider.dart';
import 'package:test_sa/service_request_latest/utilities/service_request_utils.dart';
import 'package:test_sa/views/widgets/bottom_sheets/asset_detail_bottom_sheet.dart';
import 'package:test_sa/views/widgets/date_and_time/date_picker.dart';
import 'package:test_sa/views/widgets/images/multi_image_picker.dart';
import 'package:test_sa/views/widgets/requests/request_status.dart';
import 'package:test_sa/models/device/asset.dart';
import '../../../../../models/lookup.dart';
import '../../../../../new_views/common_widgets/app_text_form_field.dart';
@ -36,8 +38,6 @@ class WoInfoForm extends StatefulWidget {
}
class _WoInfoFormState extends State<WoInfoForm> {
//TODO need to move this to provider ...
@override
void initState() {
WidgetsBinding.instance.addPostFrameCallback((_) async {
@ -78,8 +78,10 @@ class _WoInfoFormState extends State<WoInfoForm> {
'${context.translation.pmPlanNo}: ${widget.planPreventiveVisit.planNo}'.bodyText2(context).custom(color: AppColor.neutral120),
//need to add in translation it's suggestion from ahmed..
'Work Order Number: ${widget.planPreventiveVisit.visitNo}'.bodyText2(context).custom(color: AppColor.neutral120),
'${context.translation.from}: ${widget.planPreventiveVisit.fromDate?.toMonthYearFormat}'.bodyText2(context).custom(color: AppColor.neutral120),
'${context.translation.to}: ${widget.planPreventiveVisit.toDate?.toMonthYearFormat}'.bodyText2(context).custom(color: AppColor.neutral120),
'${context.translation.creationDate}: ${widget.planPreventiveVisit.creationDate?.toMonthYearFormat}'.bodyText2(context).custom(color: AppColor.neutral120),
'${context.translation.closedDate}: ${widget.planPreventiveVisit.closedDate != null ? widget.planPreventiveVisit.closedDate?.toMonthYearFormat : '-'}'
.bodyText2(context)
.custom(color: AppColor.neutral120),
'${context.translation.nextPmDate}: ${widget.planPreventiveVisit.nextPMDate != null ? widget.planPreventiveVisit.nextPMDate!.toMonthYearFormat : '-'}'
.bodyText2(context)
@ -97,7 +99,22 @@ class _WoInfoFormState extends State<WoInfoForm> {
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
widget.planPreventiveVisit.assetName!.bodyText(context).custom(color: AppColor.black10),
"info_icon".toSvgAsset(height: 17, width: 17),
"info_icon".toSvgAsset(height: 17, width: 17).onPress(
() {
// There is only limited information for asset is returned from backend to show all info need to return the whole model from backend...
showModalBottomSheet(
context: context,
isScrollControlled: true,
shape: const RoundedRectangleBorder(
borderRadius: BorderRadius.vertical(
top: Radius.circular(20),
),
),
clipBehavior: Clip.antiAliasWithSaveLayer,
builder: (BuildContext context) => _buildAssetDetailBottomSheet(context),
);
},
)
],
),
2.height,
@ -292,6 +309,23 @@ class _WoInfoFormState extends State<WoInfoForm> {
});
}
_buildAssetDetailBottomSheet(BuildContext context) {
PlanPreventiveVisit model = widget.planPreventiveVisit;
Asset asset = Asset(id: model.asset?.id, assetSerialNo: model.asset?.assetSerialNo, assetNumber: model.asset?.assetNumber);
return AssetDetailBottomSheet(asset);
}
// Future<Asset> getAssetById () async {
// Asset asset = Asset();
// AssetProvider _assetProvider = Provider.of<AssetProvider>(context, listen: false);
// if(widget.planPreventiveVisit.asset!=null){
// AssetByIdModel ?assetByIdModel = await _assetProvider.getAssetById(widget.planPreventiveVisit.asset!.id!.toInt(), context.translation);
// asss
// }
// return asset;
// }
Widget _timerWidget(BuildContext context, double totalWorkingHours) {
return Column(
children: [

@ -48,9 +48,9 @@ class AssetDetailBottomSheet extends StatelessWidget {
crossAxisAlignment: CrossAxisAlignment.start,
children: [
"${context.translation.assetNo}: ${asset!.assetNumber}".bodyText(context),
"${context.translation.modelName}: ${asset!.modelDefinition!.modelName}".bodyText(context),
"${context.translation.modelName}: ${asset!.modelDefinition?.modelName}".bodyText(context),
"${context.translation.supplier}: ${asset!.supplier?.suppliername?.cleanupWhitespace.capitalizeFirstOfEach ?? "-"}".bodyText(context),
"${context.translation.manufacture}: ${asset!.modelDefinition!.manufacturerName?.cleanupWhitespace.capitalizeFirstOfEach}".bodyText(context),
"${context.translation.manufacture}: ${asset!.modelDefinition?.manufacturerName?.cleanupWhitespace.capitalizeFirstOfEach}".bodyText(context),
//"${context.translation.location}: ${assetModel.site.custName?.cleanupWhitespace?.capitalizeFirstOfEach}".bodyText(context),
],
).expanded,

@ -18,6 +18,7 @@ class MultiFilesPicker extends StatefulWidget {
final String label;
final bool error;
final List<File> files;
final List<AttachmentModel> attachment ;
final bool enabled, onlyImages;
double? buttonHeight;
Widget? buttonIcon;
@ -28,6 +29,7 @@ class MultiFilesPicker extends StatefulWidget {
MultiFilesPicker(
{Key? key,
this.files = const <File>[],
this.attachment = const <AttachmentModel>[],
required this.label,
this.error = false,
this.buttonHeight,
@ -123,10 +125,10 @@ class _MultiFilesPickerState extends State<MultiFilesPicker> {
"Attach File".heading4(context),
12.height,
GridView(
padding: EdgeInsets.all(0),
padding: const EdgeInsets.all(0),
shrinkWrap: true,
physics: const NeverScrollableScrollPhysics(),
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 3, childAspectRatio: 1, crossAxisSpacing: 12, mainAxisSpacing: 12),
gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 3, childAspectRatio: 1, crossAxisSpacing: 12, mainAxisSpacing: 12),
children: <Widget>[
gridItem(Icons.camera_enhance_rounded, context.translation.pickFromCamera).onPress(() => Navigator.of(context).pop(ImageSource.camera)),
gridItem(Icons.image_rounded, context.translation.pickFromGallery).onPress(() => Navigator.of(context).pop(ImageSource.gallery)),
@ -141,38 +143,34 @@ class _MultiFilesPickerState extends State<MultiFilesPicker> {
).paddingAll(21),
)) as ImageSource;
if (source == null) return;
final pickedFile = await ImagePicker().pickImage(source: source, imageQuality: 70, maxWidth: 800, maxHeight: 800);
if (pickedFile != null) {
File fileImage = File(pickedFile.path);
if (fileImage != null) {
widget.files.add(fileImage);
if (widget.onChange != null) {
widget.onChange!(widget.files);
}
setState(() {});
widget.files.add(fileImage);
if (widget.onChange != null) {
widget.onChange!(widget.files);
}
}
setState(() {});
}
}
Widget gridItem(IconData iconData, String title) {
return Container(
padding: EdgeInsets.all(12),
padding: const EdgeInsets.all(12),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(12),
border: Border.all(color: Color(0xffF1F1F1), width: 1),
border: Border.all(color: const Color(0xffF1F1F1), width: 1),
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Icon(iconData, color: Color(0xff7D859A), size: 36),
Icon(iconData, color: const Color(0xff7D859A), size: 36),
Text(
title,
style: TextStyle(fontSize: 12, fontWeight: FontWeight.w500),
style: const TextStyle(fontSize: 12, fontWeight: FontWeight.w500),
),
],
),
@ -285,3 +283,295 @@ class _MultiFilesPickerState extends State<MultiFilesPicker> {
setState(() {});
}
}
class AttachmentModel {
int id =0;
File ? file;
AttachmentModel(this.id,this.file);
factory AttachmentModel.fromJson(Map<String, dynamic> json) {
return AttachmentModel(
json['id'] ?? 0,
json['file'] != null ? File(json['file']) : null,
);
}
Map<String, dynamic> toJson() {
return {
'id': id,
'file': file?.path,
};
}
}
class AttachmentPicker extends StatefulWidget {
final String label;
final bool error;
final List<AttachmentModel> attachment ;
final bool enabled, onlyImages;
double? buttonHeight;
Widget? buttonIcon;
Color? buttonColor;
final Function(List<AttachmentModel>)? onChange;
final bool showAsGrid;
AttachmentPicker(
{Key? key,
this.attachment = const <AttachmentModel>[],
required this.label,
this.error = false,
this.buttonHeight,
this.buttonIcon,
this.enabled = true,
this.onlyImages = false,
this.onChange,
this.showAsGrid = false,
this.buttonColor})
: super(key: key);
@override
State<AttachmentPicker> createState() => _AttachmentPickerState();
}
class _AttachmentPickerState extends State<AttachmentPicker> {
@override
Widget build(BuildContext context) {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
AppDashedButton(
title: widget.label,
height: widget.buttonHeight,
buttonColor: widget.buttonColor,
icon: widget.buttonIcon,
onPressed: (widget.enabled == false)
? () {}
: widget.showAsGrid
? showFileSourceSheet
: onFilePicker),
16.height,
if (widget.attachment.isNotEmpty)
Wrap(
spacing: 8.toScreenWidth,
children: List.generate(
widget.attachment.length,
(index) {
File image = widget.attachment[index].file!;
return MultiFilesPickerItem(
file: image,
enabled: widget.enabled,
onRemoveTap: (image) {
if (!widget.enabled) {
return;
}
widget.attachment.remove(image);
if (widget.onChange != null) {
widget.onChange!(widget.attachment);
}
setState(() {});
},
);
},
),
),
],
);
}
fromFilePicker() async {
FilePickerResult? result = await FilePicker.platform.pickFiles(
type: FileType.custom,
allowMultiple: true,
allowedExtensions: widget.onlyImages ? ['jpg', 'jpeg', 'png'] : ['jpg', 'jpeg', 'png', 'pdf', 'doc', 'docx', 'xlsx', 'pptx'],
);
if (result != null) {
for (var path in result.paths) {
widget.attachment.add(AttachmentModel(0, File(path!)));
}
setState(() {});
}
}
void showFileSourceSheet() async {
if (widget.attachment.length >= 5) {
Fluttertoast.showToast(msg: context.translation.maxImagesNumberIs5);
return;
}
ImageSource source = (await showModalBottomSheet(
context: context,
shape: const RoundedRectangleBorder(
borderRadius: BorderRadius.vertical(
top: Radius.circular(20),
),
),
clipBehavior: Clip.antiAliasWithSaveLayer,
builder: (BuildContext context) => Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
"Attach File".heading4(context),
12.height,
GridView(
padding: const EdgeInsets.all(0),
shrinkWrap: true,
physics: const NeverScrollableScrollPhysics(),
gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 3, childAspectRatio: 1, crossAxisSpacing: 12, mainAxisSpacing: 12),
children: <Widget>[
gridItem(Icons.camera_enhance_rounded, context.translation.pickFromCamera).onPress(() => Navigator.of(context).pop(ImageSource.camera)),
gridItem(Icons.image_rounded, context.translation.pickFromGallery).onPress(() => Navigator.of(context).pop(ImageSource.gallery)),
gridItem(Icons.file_present_rounded, context.translation.pickFromFiles).onPress(() async {
await fromFilePicker();
Navigator.pop(context);
}),
],
),
12.height,
],
).paddingAll(21),
)) as ImageSource;
final pickedFile = await ImagePicker().pickImage(source: source, imageQuality: 70, maxWidth: 800, maxHeight: 800);
if (pickedFile != null) {
File fileImage = File(pickedFile.path);
widget.attachment.add(AttachmentModel(0, fileImage));
if (widget.onChange != null) {
widget.onChange!(widget.attachment);
}
setState(() {});
}
}
Widget gridItem(IconData iconData, String title) {
return Container(
padding: const EdgeInsets.all(12),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(12),
border: Border.all(color: const Color(0xffF1F1F1), width: 1),
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Icon(iconData, color: const Color(0xff7D859A), size: 36),
Text(
title,
style: const TextStyle(fontSize: 12, fontWeight: FontWeight.w500),
),
],
),
);
}
onFilePicker() async {
if (widget.attachment.length >= 5) {
Fluttertoast.showToast(msg: context.translation.maxImagesNumberIs5);
return;
}
ImageSource? source = await showModalBottomSheet<ImageSource>(
context: context,
builder: (BuildContext context) {
Widget listCard({required String icon, required String label, required VoidCallback onTap}){
return GestureDetector(
onTap: onTap,
child: Container(
constraints: BoxConstraints(minWidth: 111.toScreenWidth,minHeight: 111.toScreenHeight),
padding: EdgeInsets.symmetric(horizontal: 12.toScreenWidth,vertical: 12.toScreenHeight),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(12),
border: Border.all(width: 1,color:AppColor.white70)
),
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
icon.toSvgAsset(),
24.height,
label.bodyText2(context).custom(color: AppColor.black20),
],
),
),
);
}
return Container(
padding: const EdgeInsets.all(16.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
listCard(
icon: 'camera_icon',
label: '${context.translation.open}\n${context.translation.camera}',
onTap: () {
Navigator.of(context).pop(ImageSource.camera);
},
),
listCard(
icon: 'gallery_icon',
label: '${context.translation.open}\n${context.translation.gallery}',
onTap: () {
Navigator.of(context).pop(ImageSource.gallery);
},
),
listCard(
icon: 'file_icon',
label: '${context.translation.open}\n${context.translation.files}',
onTap: () async {
await fromFilePicker();
Navigator.pop(context);
},
),
],
),
);
},
);
// ImageSource source = await showDialog(
// context: context,
// builder: (dialogContext) => CupertinoAlertDialog(
// actions: <Widget>[
// TextButton(
// child: Text(context.translation.pickFromCamera),
// onPressed: () {
// Navigator.of(dialogContext).pop(ImageSource.camera);
// },
// ),
// TextButton(
// child: Text(context.translation.pickFromGallery),
// onPressed: () {
// Navigator.of(dialogContext).pop(ImageSource.gallery);
// },
// ),
// TextButton(
// child: Text(context.translation.pickFromFiles),
// onPressed: () async {
// await fromFilePicker();
// Navigator.pop(context);
// },
// ),
// ],
// ),
// );
if (source == null) return;
final pickedFile = await ImagePicker().pickImage(source: source, imageQuality: 70, maxWidth: 800, maxHeight: 800);
if (pickedFile != null) {
File fileImage = File(pickedFile.path);
widget.attachment.add(AttachmentModel(0, fileImage));
if (widget.onChange != null) {
widget.onChange!(widget.attachment);
}
setState(() {});
}
setState(() {});
}
}

Loading…
Cancel
Save