Merge remote-tracking branch 'origin/main_design2.0' into main_design2.0

# Conflicts:
#	lib/l10n/app_ar.arb
#	lib/l10n/app_en.arb
#	lib/new_views/common_widgets/single_item_drop_down_menu.dart
main_design2.0
nextwo 2 years ago
commit e21bde0153

@ -0,0 +1,3 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M13.6572 2.34321C12.1569 0.842876 10.122 -1.58085e-08 8.00021 0C5.87842 1.58085e-08 3.84354 0.842877 2.34321 2.34321C0.842877 3.84354 1.58085e-08 5.87842 0 8.00021C-1.58085e-08 10.122 0.842876 12.1569 2.34321 13.6572C3.84354 15.1575 5.87842 16.0004 8.00021 16.0004C10.122 16.0004 12.1569 15.1575 13.6572 13.6572C15.1575 12.1569 16.0004 10.122 16.0004 8.00021C16.0004 5.87842 15.1575 3.84354 13.6572 2.34321ZM11.4572 10.3552C11.5405 10.4247 11.6085 10.5108 11.6567 10.608C11.7049 10.7052 11.7323 10.8114 11.7372 10.9198C11.7421 11.0281 11.7244 11.1364 11.6851 11.2375C11.6459 11.3387 11.586 11.4305 11.5093 11.5073C11.4325 11.584 11.3407 11.6439 11.2395 11.6831C11.1384 11.7224 11.0301 11.7401 10.9218 11.7352C10.8134 11.7303 10.7072 11.7029 10.61 11.6547C10.5128 11.6065 10.4267 11.5385 10.3572 11.4552L8.00021 9.10021L5.64521 11.4602C5.49549 11.5851 5.3045 11.6494 5.10976 11.6406C4.91502 11.6318 4.7306 11.5505 4.59276 11.4127C4.45492 11.2748 4.37361 11.0904 4.36481 10.8957C4.35601 10.7009 4.42036 10.5099 4.54521 10.3602L6.90021 8.00021L4.54021 5.64521C4.41536 5.49549 4.35101 5.3045 4.35981 5.10976C4.36861 4.91502 4.44992 4.7306 4.58776 4.59276C4.7256 4.45492 4.91002 4.37361 5.10476 4.36481C5.2995 4.35601 5.49049 4.42036 5.64021 4.54521L8.00021 6.90021L10.3552 4.54021C10.5049 4.41536 10.6959 4.35101 10.8907 4.35981C11.0854 4.36861 11.2698 4.44992 11.4077 4.58776C11.5455 4.7256 11.6268 4.91002 11.6356 5.10476C11.6444 5.2995 11.5801 5.49049 11.4552 5.64021L9.10021 8.00021L11.4572 10.3552Z" fill="#CA3332"/>
</svg>

After

Width:  |  Height:  |  Size: 1.6 KiB

@ -1,14 +1,18 @@
import 'dart:convert';
import 'dart:developer';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:fluttertoast/fluttertoast.dart';
import 'package:http/http.dart';
import 'package:test_sa/controllers/api_routes/api_manager.dart';
import 'package:test_sa/controllers/api_routes/urls.dart';
import 'package:test_sa/extensions/context_extension.dart';
import 'package:test_sa/models/device/asset_transfer.dart';
import 'package:test_sa/models/device/device.dart';
import 'package:test_sa/models/user.dart';
import '../../../models/hospital.dart';
import '../../../new_views/common_widgets/app_lazy_loading.dart';
class AssetTransferProvider extends ChangeNotifier {
// number of items call in each request
@ -117,51 +121,15 @@ class AssetTransferProvider extends ChangeNotifier {
}
}
Future<int> createRequest({
@required String host,
@required User user,
@required AssetTransfer model,
Future<void> createRequest({
@required BuildContext context,
@required AssetTransfer assetDestination,
@required Device asset,
}) async {
Map<String, dynamic> body = {
"id": 0,
// "assetId": model.device.id ?? "",
"destSiteId": hospital.id ?? "",
"destDepartmentId": department.id ?? "",
// "senderSiteId": model.sender.client.id ?? "",
// "transferNo": 0,
// "transferCode": "string",
"destBuildingId": building?.id,
"destFloorId": floor.id,
"destRoom": room,
/////
// "senderBuildingId": model.device.destBuildingId,
// "senderFloorId": model.device.destFloorId,
// "senderDepartmentId": model.device.destDepartmentId,
// "senderRoom": model.device.destRoom,
// if (model?.sender?.attachments?.isNotEmpty ?? false)
// "senderAttachments":
// model?.sender?.attachments?.map((file) => {"attachmentName": _isLocalUrl(file.path) ? ("${file.path.split("/").last}|${base64Encode(file.readAsBytesSync())}") : file.path})?.toList(),
// "senderAssignedEmployeeId": "string",
// "senderMachineStatusId": 0,
// "senderComment": "string",
// "senderStartDate": "2023-06-11T09:21:56.453Z",
// "senderEndDate": "2023-06-11T09:21:56.453Z",
// "senderWorkingHours": "string",
// "senderTravelingHours": "string",
// "senderAttachmentName": "string",
// "receiverAssignedEmployeeId": "string",
// "receiverMachineStatusId": 0,
// "receiverComment": "string",
// "receiverStartDate": "2023-06-11T09:21:56.453Z",
// "receiverEndDate": "2023-06-11T09:21:56.453Z",
// "receiverWorkingHours": "string",
// "receiverTravelingHours": "string",
// "receiverAttachmentName": "string"
};
Response response;
try {
response = await ApiManager.instance.post(URLs.requestDeviceTransfer, body: body);
showDialog(context: context, barrierDismissible: false, builder: (context) => const AppLazyLoading());
response = await ApiManager.instance.post(URLs.requestDeviceTransfer, body: assetDestination.transferBody(asset: asset));
stateCode = response.statusCode;
if (response.statusCode >= 200 && response.statusCode < 300) {
if (items != null) {
@ -169,10 +137,14 @@ class AssetTransferProvider extends ChangeNotifier {
reset();
notifyListeners();
}
Fluttertoast.showToast(msg: context.translation.createdSuccessfully);
} else {
Fluttertoast.showToast(msg: "${context.translation.failedToCompleteRequest} :${json.decode(response.body)['message']}");
}
return response.statusCode;
Navigator.pop(context);
} catch (error) {
return -1;
Navigator.pop(context);
print(error);
}
}

@ -1,16 +1,20 @@
import 'dart:convert';
import 'dart:developer';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:fluttertoast/fluttertoast.dart';
import 'package:http/http.dart';
import 'package:test_sa/controllers/api_routes/api_manager.dart';
import 'package:test_sa/controllers/api_routes/urls.dart';
import 'package:test_sa/extensions/context_extension.dart';
import 'package:test_sa/models/gas_refill/gas_refill_model.dart';
import 'package:test_sa/models/hospital.dart';
import 'package:test_sa/models/new_models/gas_refill_model.dart' as gasModel;
import 'package:test_sa/models/timer_model.dart';
import 'package:test_sa/models/user.dart';
import '../../../new_views/common_widgets/app_lazy_loading.dart';
class GasRefillProvider extends ChangeNotifier {
// number of items call in each request
final pageItemNumber = 12;
@ -89,37 +93,19 @@ class GasRefillProvider extends ChangeNotifier {
}
}
Future<int> createModel({
Future<void> createModel({
@required BuildContext context,
@required User user,
@required gasModel.GasRefillModel model,
}) async {
Map<String, dynamic> body = {
"uid": user.id.toString(),
"token": user.token ?? "",
"site": model.site?.toJson(),
"building": model.building != null ? {"id": model.building?.id, "name": model.building?.name, "value": model.building?.value} : null,
"floor": model.floor != null ? {"id": model.floor?.id, "name": model.floor?.name, "value": model.floor?.value} : null,
//if (expectedDateTime != null) "expectedDate": expectedDateTime?.toIso8601String(),
if (expectedDateTime != null) "expectedTime": expectedDateTime?.toIso8601String(),
if (timer?.startAt != null) "startDate": timer.startAt.toIso8601String(),
if (timer?.startAt != null) "startTime": timer.startAt.toIso8601String(),
if (timer?.endAt != null) "endDate": timer.endAt.toIso8601String(),
if (timer?.endAt != null) "endTime": timer.endAt.toIso8601String(),
"department": model.department?.toJson(),
"GazRefillNo": "GR-${DateTime.now().toString().split(" ").first}",
"status": model.status?.toJson(),
};
body["gazRefillDetails"] = model.gazRefillDetails
.map((model) => {
"gasType": model.gasType.toJson(),
"cylinderSize": model.cylinderSize.toJson(),
"cylinderType": model.cylinderType.toJson(),
"requestedQty": model.requestedQty,
})
.toList();
Response response;
try {
showDialog(context: context, barrierDismissible: false, builder: (context) => const AppLazyLoading());
final body = model.toJson()
..addAll({
"uid": user.id.toString(),
"token": user.token ?? "",
});
response = await ApiManager.instance.post(URLs.requestGasRefill, body: body);
stateCode = response.statusCode;
if (response.statusCode >= 200 && response.statusCode < 300) {
@ -127,11 +113,15 @@ class GasRefillProvider extends ChangeNotifier {
reset();
notifyListeners();
}
Fluttertoast.showToast(msg: context.translation.createdSuccessfully);
Navigator.pop(context);
} else {
Fluttertoast.showToast(msg: "${context.translation.failedToCompleteRequest} :${json.decode(response.body)['message']}");
}
return response.statusCode;
Navigator.pop(context);
} catch (error) {
Navigator.pop(context);
print(error);
return -1;
}
}

@ -1,23 +1,26 @@
import 'dart:convert';
import 'dart:developer';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import 'package:fluttertoast/fluttertoast.dart';
import 'package:http/http.dart';
import 'package:test_sa/controllers/api_routes/api_manager.dart';
import 'package:test_sa/controllers/api_routes/http_status_manger.dart';
import 'package:test_sa/controllers/api_routes/urls.dart';
import 'package:test_sa/extensions/context_extension.dart';
import 'package:test_sa/models/call_request_for_work_order_model.dart';
import 'package:test_sa/models/issue.dart';
import 'package:test_sa/models/lookup.dart';
import 'package:test_sa/models/service_report.dart';
import 'package:test_sa/models/service_request/service_request.dart';
import 'package:test_sa/models/service_request/service_request_search.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import 'package:test_sa/models/timer_model.dart';
import '../../../models/service_request/search_work_order.dart';
import '../../../models/service_request/sub_work_order_details.dart';
import '../../../models/user.dart';
import '../../../new_views/common_widgets/app_lazy_loading.dart';
class ServiceRequestsProvider extends ChangeNotifier {
// number of items call in each request
@ -131,7 +134,8 @@ class ServiceRequestsProvider extends ChangeNotifier {
}
}
Future<int> createRequest({
Future<void> createRequest({
@required BuildContext context,
@required String host,
@required User user,
@required ServiceRequest serviceRequest,
@ -140,7 +144,7 @@ class ServiceRequestsProvider extends ChangeNotifier {
"id": 0,
"calNo": "",
"callCreatedBy": {"id": user.userID, "name": user.userName ?? ""},
"assets": serviceRequest.deviceId == null ? [] : [serviceRequest.deviceId],
"assets": serviceRequest.device?.id == null ? [] : [serviceRequest.device?.id],
"requestedDate": DateTime.now().toIso8601String(),
"requestedTime": DateTime.now().toIso8601String(),
"client": user.clientId,
@ -177,27 +181,33 @@ class ServiceRequestsProvider extends ChangeNotifier {
if (serviceRequest.audio != null) {
body["voiceNote"] = serviceRequest.audio;
}
showDialog(context: context, barrierDismissible: false, builder: (context) => const AppLazyLoading());
Response response;
//try {
response = await ApiManager.instance.post(URLs.createRequest, body: body);
stateCode = response.statusCode;
if (response.statusCode >= 200 && response.statusCode < 300) {
if (serviceRequests != null) {
var data = json.decode(utf8.decode(response.bodyBytes));
if (data is List) {
serviceRequests.insert(0, ServiceRequest.fromJson(data[0]));
} else {
if (data["data"] != null && data["data"] == true) {
// serviceRequests.insert(0, ServiceRequest.fromJson(data[0]));
try {
response = await ApiManager.instance.post(URLs.createRequest, body: body);
stateCode = response.statusCode;
if (response.statusCode >= 200 && response.statusCode < 300) {
if (serviceRequests != null) {
var data = json.decode(utf8.decode(response.bodyBytes));
if (data is List) {
serviceRequests.insert(0, ServiceRequest.fromJson(data[0]));
} else {
if (data["data"] != null && data["data"] == true) {
// serviceRequests.insert(0, ServiceRequest.fromJson(data[0]));
}
}
}
notifyListeners();
Fluttertoast.showToast(msg: context.translation.successfulRequestMessage);
Navigator.pop(context);
} else {
Fluttertoast.showToast(msg: "${context.translation.failedRequestMessage} :${json.decode(response.body)['message']}");
}
notifyListeners();
Navigator.pop(context);
} catch (error) {
print(error);
Navigator.pop(context);
}
return response.statusCode;
// } catch (error) {
// return -1;
// }
}
Future<int> createIssueReport({

@ -6,6 +6,8 @@ import 'package:test_sa/controllers/api_routes/api_manager.dart';
import 'package:test_sa/controllers/api_routes/urls.dart';
import 'package:test_sa/models/user.dart';
import '../../../new_views/common_widgets/app_lazy_loading.dart';
class UserProvider extends ChangeNotifier {
//reset provider data
void reset() {
@ -39,12 +41,13 @@ class UserProvider extends ChangeNotifier {
/// return state code if request complete may be 200, 404 or 403
/// for more details check http state manager
/// lib\controllers\http_status_manger\http_status_manger.dart
Future<int> login({@required User user}) async {
Future<int> login({@required BuildContext context, @required User user}) async {
if (_loading == true) return -2;
_loading = true;
notifyListeners();
Response response;
try {
showDialog(context: context, barrierDismissible: false, builder: (context) => const AppLazyLoading());
response = await ApiManager.instance.post(URLs.login, body: await user.toLoginJson());
_loading = false;
if (response.statusCode >= 200 && response.statusCode < 300) {
@ -55,8 +58,10 @@ class UserProvider extends ChangeNotifier {
return response.statusCode;
}
notifyListeners();
Navigator.pop(context);
return response.statusCode;
} catch (error) {
Navigator.pop(context);
debugPrint(error);
_loading = false;
notifyListeners();

@ -250,7 +250,7 @@
"assetNo" : "رقم الجهاز",
"manufacture" : "صناعة",
"model" : "الطراز",
"serialNumber" : "الرقم التسلسلي",
"Serial No" : "الرقم التسلسلي",
"device" : "الجهاز",
"pickAsset" : "إختر جهاز",
"filter" : "تصنيف",
@ -264,5 +264,11 @@
"recordVoice" : "تسجيل صوت",
"gasRefillDetails" : "تفاصيل اعادة تعبئة غاز",
"updateRequest" : "تعديل الطلب",
"gasRefill" : "اعادة تعبئة غاز"
"gasRefill" : "اعادة تعبئة غاز",
"recordVoice" : "تسجيل صوت",
"receiverName" : "اسم المستلم",
"receiverDetails" : "تفاصيل المستلم",
"requestedThrough" : "الطلب عبر",
"typeOfRequest" : "نوع الطلب",
"assetDetails" : "تفاصيل الجهاز"
}

@ -250,7 +250,6 @@
"assetNo" : "Asset No.",
"manufacture" : "Manufacture",
"model" : "Model",
"serialNumber" : "Serial Number",
"serialNo" : "Serial No",
"device" : "Device",
"pickAsset" : "Pick Asset",
@ -272,5 +271,9 @@
"updateRequest" : "Update Request",
"gasRefill" : "Gas Refill",
"recordVoice" : "Record Voice",
"assetDetails" : "Asset Details"
"assetDetails" : "Asset Details",
"receiverName" : "Receiver Name",
"receiverDetails" : "Receiver Details",
"requestedThrough" : "Requested Through",
"typeOfRequest" : "Type of Request"
}

@ -45,7 +45,6 @@ import 'package:test_sa/controllers/providers/api/status_drop_down/service_reqes
import 'package:test_sa/new_views/app_style/app_themes.dart';
import 'package:test_sa/new_views/pages/land_page/land_page.dart';
import 'package:test_sa/new_views/pages/login_page.dart';
import 'package:test_sa/new_views/pages/new_transfer_request_page.dart';
import 'package:test_sa/new_views/pages/splash_page.dart';
import 'package:test_sa/providers/department_provider.dart';
import 'package:test_sa/providers/gas_request_providers/cylinder_size_provider.dart';
@ -56,6 +55,8 @@ import 'package:test_sa/providers/gas_request_providers/site_provider.dart';
import 'package:test_sa/providers/loading_list_notifier.dart';
import 'package:test_sa/providers/service_request_providers/equipment_status_provider.dart';
import 'package:test_sa/providers/service_request_providers/priority_provider.dart';
import 'package:test_sa/providers/service_request_providers/requested_through_provider.dart';
import 'package:test_sa/providers/service_request_providers/type_of_request_provider.dart';
import 'package:test_sa/views/pages/device_transfer/request_device_transfer.dart';
import 'package:test_sa/views/pages/device_transfer/track_device_transfer.dart';
import 'package:test_sa/views/pages/sub_workorder/create_sub_workorder_page.dart';
@ -161,6 +162,8 @@ class MyApp extends StatelessWidget {
ChangeNotifierProvider(create: (_) => ServiceReportAssistantsEmployeeProvider()),
ChangeNotifierProvider(create: (_) => PriorityProvider()),
ChangeNotifierProvider(create: (_) => EquipmentStatusProvider()),
ChangeNotifierProvider(create: (_) => RequestedThroughProvider()),
ChangeNotifierProvider(create: (_) => TypeOfRequestProvider()),
],
child: GestureDetector(
onTap: () {
@ -183,7 +186,6 @@ class MyApp extends StatelessWidget {
old.LandPage.id: (_) => const old.LandPage(),
LandPage.routeName: (_) => const LandPage(),
NewGasRefillRequestPage.routeName: (_) => const NewGasRefillRequestPage(),
NewTransferRequestPage.routeName: (_) => const NewTransferRequestPage(),
ServiceRequestsPage.id: (_) => ServiceRequestsPage(),
ReportIssuesPage.id: (_) => const ReportIssuesPage(),
RequestGasRefill.id: (_) => const RequestGasRefill(),

@ -1,3 +1,8 @@
import 'package:flutter/src/widgets/framework.dart';
import 'package:fluttertoast/fluttertoast.dart';
import 'package:test_sa/extensions/context_extension.dart';
import 'package:test_sa/models/device/device.dart';
import 'asset_transfer_attachment.dart';
class AssetTransfer {
@ -220,4 +225,65 @@ class AssetTransfer {
}
return map;
}
Map<String, dynamic> transferBody({Device asset}) {
final map = <String, dynamic>{};
map['id'] = 0;
map['transferNo'] = transferNo;
map['transferCode'] = transferCode;
map['assetId'] = asset?.id;
map['destSiteId'] = destSiteId;
map['destBuildingId'] = destBuildingId;
map['destFloorId'] = destFloorId;
map['destDepartmentId'] = destDepartmentId;
map['destRoom'] = destRoom;
map['senderSiteId'] = asset?.site?.id;
map['senderBuildingId'] = asset?.building?.id;
map['senderFloorId'] = asset?.floor?.id;
map['senderDepartmentId'] = asset?.department?.id;
map['senderRoom'] = asset?.room;
map['senderAssignedEmployeeId'] = senderAssignedEmployeeId;
map['senderMachineStatusId'] = senderMachineStatusId;
map['senderComment'] = senderComment;
map['senderStartDate'] = senderStartDate;
map['senderEndDate'] = senderEndDate;
map['senderWorkingHours'] = senderWorkingHours;
map['senderTravelingHours'] = senderTravelingHours;
map['senderEngSignature'] = senderEngSignature;
if (senderAttachments != null) {
map['senderAttachments'] = senderAttachments.map((v) => v.toJson()).toList();
}
map['receiverAssignedEmployeeId'] = receiverAssignedEmployeeId;
map['receiverMachineStatusId'] = receiverMachineStatusId;
map['receiverComment'] = receiverComment;
map['receiverStartDate'] = receiverStartDate;
map['receiverEndDate'] = receiverEndDate;
map['receiverWorkingHours'] = receiverWorkingHours;
map['receiverTravelingHours'] = receiverTravelingHours;
map['receiverEngSignature'] = receiverEngSignature;
if (receiverAttachments != null) {
map['receiverAttachments'] = receiverAttachments.map((v) => v.toJson()).toList();
}
return map;
}
Future<bool> validate(BuildContext context) async {
if (assetId == null) {
await Fluttertoast.showToast(msg: "${context.translation.youHaveToSelect} ${context.translation.device}");
return false;
} else if (destSiteId == null) {
await Fluttertoast.showToast(msg: "${context.translation.youHaveToSelect} ${context.translation.destinationSite}");
return false;
} else if (destBuildingId == null) {
await Fluttertoast.showToast(msg: "${context.translation.youHaveToSelect} ${context.translation.building}");
return false;
} else if (destFloorId == null) {
await Fluttertoast.showToast(msg: "${context.translation.youHaveToSelect} ${context.translation.floor}");
return false;
} else if (destDepartmentId == null) {
await Fluttertoast.showToast(msg: "${context.translation.youHaveToSelect} ${context.translation.department}");
return false;
}
return true;
}
}

@ -4,7 +4,6 @@ import 'dart:typed_data';
import 'package:flutter/cupertino.dart';
import 'package:fluttertoast/fluttertoast.dart';
import 'package:test_sa/extensions/context_extension.dart';
import 'package:test_sa/models/enums/translation_keys.dart';
import 'package:test_sa/models/lookup.dart';
import 'package:test_sa/models/new_models/assigned_employee.dart';
import 'package:test_sa/models/new_models/building.dart';
@ -126,8 +125,8 @@ class GasRefillModel {
Map<String, dynamic> toJson() {
final map = <String, dynamic>{};
map['id'] = id;
map['gazRefillNo'] = gazRefillNo;
map['id'] = id ?? 0;
map['gazRefillNo'] = "GR-${DateTime.now().toString().split(" ").first}";
map['expectedDate'] = expectedDate;
map['expectedTime'] = expectedTime;
map['startDate'] = startDate;
@ -247,7 +246,7 @@ class GasRefillDetails {
Map<String, dynamic> toJson() {
final map = <String, dynamic>{};
map['id'] = id;
map['id'] = id ?? 0;
if (gasType != null) {
map['gasType'] = gasType.toJson();
}

@ -152,6 +152,12 @@ class ServiceRequest {
} else if (defectType == null) {
await Fluttertoast.showToast(msg: "${context.translation.youHaveToSelect} ${context.translation.equipmentStatus}");
return false;
} else if (requestedThrough == null) {
await Fluttertoast.showToast(msg: "${context.translation.youHaveToSelect} ${context.translation.requestedThrough}");
return false;
} else if (type == null) {
await Fluttertoast.showToast(msg: "${context.translation.youHaveToSelect} ${context.translation.typeOfRequest}");
return false;
}
return true;
}

@ -4,13 +4,12 @@ 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 '../../models/enums/translation_keys.dart';
import '../app_style/app_color.dart';
class DefaultAppBar extends StatelessWidget implements PreferredSizeWidget {
final String title;
const DefaultAppBar({@required this.title, Key key}) : super(key: key);
const DefaultAppBar({this.title, Key key}) : super(key: key);
@override
Widget build(BuildContext context) {
@ -23,7 +22,7 @@ class DefaultAppBar extends StatelessWidget implements PreferredSizeWidget {
Navigator.of(context).pop();
}),
Text(
title,
title ?? "",
style: AppTextStyles.heading3?.copyWith(fontWeight: FontWeight.w600, color: context.isDark ? AppColor.neutral30 : AppColor.neutral50),
).expanded,
],

@ -2,7 +2,6 @@ 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/models/enums/translation_keys.dart';
import 'package:test_sa/new_views/common_widgets/app_loading_manager.dart';
import 'package:test_sa/providers/loading_list_notifier.dart';
@ -47,7 +46,7 @@ class _SingleItemDropDownMenuState<T extends Base, X extends LoadingListNotifier
return element == widget.initialValue;
});
if (result?.isNotEmpty??false) _selectedItem = result.first;
if ((widget.initialValue?.identifier ?? "") != (_selectedItem?.identifier ?? "")) {
if (widget.onSelect != null && (widget.initialValue?.identifier ?? "") != (_selectedItem?.identifier ?? "")) {
widget.onSelect(_selectedItem);
}
}
@ -70,7 +69,7 @@ class _SingleItemDropDownMenuState<T extends Base, X extends LoadingListNotifier
} else {
_selectedItem = null;
}
if ((widget.initialValue?.identifier ?? "") != (_selectedItem?.identifier ?? "")) {
if (widget.onSelect != null && (widget.initialValue?.identifier ?? "") != (_selectedItem?.identifier ?? "")) {
widget.onSelect(_selectedItem);
}
} else {
@ -119,7 +118,7 @@ class _SingleItemDropDownMenuState<T extends Base, X extends LoadingListNotifier
elevation: 0,
isExpanded: true,
hint: Text(
context.translation.select,
context.translation.select,
style: Theme.of(context).textTheme.bodyLarge,
),
style: TextStyle(color: Theme.of(context).primaryColor),

@ -5,9 +5,7 @@ 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/translation_keys.dart';
import 'package:test_sa/new_views/app_style/app_color.dart';
import 'package:test_sa/new_views/common_widgets/app_lazy_loading.dart';
import '../../controllers/providers/api/user_provider.dart';
import '../../controllers/providers/settings/setting_provider.dart';
@ -98,9 +96,7 @@ class _LoginPageState extends State<LoginPage> {
Future<void> _login() async {
if (!_formKey.currentState.validate()) return;
_formKey.currentState.save();
showDialog(context: context, barrierDismissible: false, builder: (context) => const AppLazyLoading());
int status = await _userProvider.login(user: _user);
Navigator.pop(context);
int status = await _userProvider.login(context: context, user: _user);
if (status >= 200 && status < 300 && _userProvider.user.isAuthenticated ?? false) {
_settingProvider.setUser(_userProvider.user);

@ -6,7 +6,6 @@ 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/translation_keys.dart';
import 'package:test_sa/models/lookup.dart';
import 'package:test_sa/models/new_models/building.dart';
import 'package:test_sa/models/new_models/department.dart';
@ -25,7 +24,6 @@ import 'package:test_sa/providers/loading_list_notifier.dart';
import '../../controllers/providers/api/gas_refill_provider.dart';
import '../../controllers/validator/validator.dart';
import '../common_widgets/app_lazy_loading.dart';
import '../common_widgets/default_app_bar.dart';
class NewGasRefillRequestPage extends StatefulWidget {
@ -95,6 +93,7 @@ class _NewGasRefillRequestPageState extends State<NewGasRefillRequestPage> {
SingleItemDropDownMenu<Lookup, CylinderTypesProvider>(
context: context,
title: context.translation.cylinderType,
initialValue: _currentDetails.cylinderType,
onSelect: (value) {
_currentDetails.cylinderType = value;
},
@ -103,6 +102,7 @@ class _NewGasRefillRequestPageState extends State<NewGasRefillRequestPage> {
SingleItemDropDownMenu<Lookup, CylinderSizeProvider>(
context: context,
title: context.translation.cylinderSize,
initialValue: _currentDetails.cylinderSize,
onSelect: (value) {
_currentDetails.cylinderSize = value;
},
@ -115,6 +115,9 @@ class _NewGasRefillRequestPageState extends State<NewGasRefillRequestPage> {
onSelect: (value) {
setState(() {
_gasModel.site = value;
_gasModel?.building = null;
_gasModel?.floor = null;
_gasModel?.department = null;
});
},
),
@ -128,6 +131,8 @@ class _NewGasRefillRequestPageState extends State<NewGasRefillRequestPage> {
onSelect: (value) {
setState(() {
_gasModel.building = value;
_gasModel?.floor = null;
_gasModel?.department = null;
});
},
),
@ -141,6 +146,7 @@ class _NewGasRefillRequestPageState extends State<NewGasRefillRequestPage> {
onSelect: (value) {
setState(() {
_gasModel.floor = value;
_gasModel?.department = null;
});
},
),
@ -242,18 +248,10 @@ class _NewGasRefillRequestPageState extends State<NewGasRefillRequestPage> {
Fluttertoast.showToast(msg: context.translation.youHaveToAddRequests);
return;
}
showDialog(context: context, barrierDismissible: false, builder: (context) => const AppLazyLoading());
final status = await Provider.of<GasRefillProvider>(context, listen: false).createModel(
await Provider.of<GasRefillProvider>(context, listen: false).createModel(
context: context,
user: Provider.of<UserProvider>(context, listen: false).user,
model: _gasModel,
);
Navigator.pop(context);
if (status >= 200 && status < 300) {
Fluttertoast.showToast(msg: context.translation.createdSuccessfully);
Navigator.of(context).pop();
setState(() {});
} else {
Fluttertoast.showToast(msg: context.translation.failedToCompleteRequest);
}
}
}

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

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

@ -3,23 +3,25 @@ import 'package:provider/provider.dart';
import 'package:test_sa/controllers/providers/api/asset_transfer_provider.dart';
import 'package:test_sa/controllers/providers/api/user_provider.dart';
import 'package:test_sa/controllers/providers/settings/setting_provider.dart';
import 'package:test_sa/controllers/validator/validator.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/device/asset_transfer.dart';
import 'package:test_sa/models/subtitle.dart';
import 'package:test_sa/views/app_style/sizing.dart';
import 'package:test_sa/views/widgets/buttons/app_button.dart';
import 'package:test_sa/views/widgets/loaders/loading_manager.dart';
import 'package:test_sa/views/widgets/titles/app_sub_title.dart';
import 'package:test_sa/models/device/device.dart';
import 'package:test_sa/models/new_models/department.dart';
import 'package:test_sa/models/new_models/floor.dart';
import 'package:test_sa/new_views/common_widgets/app_text_form_field.dart';
import '../../../../controllers/localization/localization.dart';
import '../../../controllers/validator/validator.dart';
import '../../app_style/colors.dart';
import '../../widgets/app_text_form_field.dart';
import '../../widgets/gas_refill/building_type_menu.dart';
import '../../widgets/gas_refill/department_type_menu.dart';
import '../../widgets/gas_refill/floor_type_menu.dart';
import '../../widgets/hospitals/hospital_auto_complete_field_new.dart';
import '../../../models/new_models/building.dart';
import '../../../models/new_models/site.dart';
import '../../../new_views/common_widgets/app_filled_button.dart';
import '../../../new_views/common_widgets/default_app_bar.dart';
import '../../../new_views/common_widgets/single_item_drop_down_menu.dart';
import '../../../providers/gas_request_providers/site_provider.dart';
import '../../../providers/loading_list_notifier.dart';
import '../../widgets/equipment/pick_asset.dart';
class RequestDeviceTransfer extends StatefulWidget {
static const String id = "/request-device-transfer";
@ -31,287 +33,148 @@ class RequestDeviceTransfer extends StatefulWidget {
}
class _RequestDeviceTransferState extends State<RequestDeviceTransfer> {
bool _isLoading = false;
bool _validate = false;
UserProvider _userProvider;
SettingProvider _settingProvider;
AssetTransferProvider _deviceTransferProvider;
final TextEditingController _requestedQuantityController = TextEditingController();
final AssetTransfer _formModel = AssetTransfer(/*receiver: DeviceTransferInfo(), sender: DeviceTransferInfo()*/);
final AssetTransfer _transferModel = AssetTransfer();
final GlobalKey<FormState> _formKey = GlobalKey<FormState>();
final GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>();
final TextEditingController _receiverNameController = TextEditingController(), _commentsController = TextEditingController();
final Device _assetDestination = Device();
Device _pickedAsset;
@override
void setState(VoidCallback fn) {
if (mounted) super.setState(() {});
}
_onSubmit() async {
_validate = true;
if (!_formKey.currentState.validate()) {
setState(() {});
return false;
void _onSubmit() async {
_transferModel.assetId = _pickedAsset.id;
_transferModel.destSiteId = _assetDestination.site?.id;
_transferModel.destBuildingId = _assetDestination.building?.id;
_transferModel.destFloorId = _assetDestination.floor?.id;
_transferModel.destDepartmentId = _assetDestination.department?.id;
if (!_formKey.currentState.validate() || !(await _transferModel.validate(context))) {
return;
}
_formKey.currentState.save();
// if (!_formModel.validate()) {
// setState(() {});
// return false;
// }
_isLoading = true;
setState(() {});
// _formModel.sender?.client?.id = _userProvider.user?.clientId;
int status = await _deviceTransferProvider.createRequest(
user: _userProvider.user,
host: _settingProvider.host,
model: _formModel,
);
_isLoading = false;
setState(() {});
if (status >= 200 && status < 300) {
// Fluttertoast.showToast(
// msg: _subtitle.requestCompleteSuccessfully,
// );
Navigator.of(context).pop();
}
// else {
// String errorMessage = HttpStatusManger.getStatusMessage(status: status, subtitle: _subtitle);
// ScaffoldMessenger.of(context).showSnackBar(SnackBar(
// content: Text(errorMessage),
// ));
// }
await _deviceTransferProvider.createRequest(context: context, assetDestination: _transferModel, asset: _pickedAsset);
}
@override
void dispose() {
_requestedQuantityController.dispose();
_deviceTransferProvider.reset();
_receiverNameController.dispose();
_commentsController.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
_userProvider = Provider.of<UserProvider>(context);
_settingProvider = Provider.of<SettingProvider>(context);
_userProvider = Provider.of<UserProvider>(context, listen: false);
_settingProvider = Provider.of<SettingProvider>(context, listen: false);
_deviceTransferProvider = Provider.of<AssetTransferProvider>(context, listen: false);
return Scaffold(
key: _scaffoldKey,
appBar: DefaultAppBar(title: context.translation.newTransferRequest),
body: Form(
key: _formKey,
child: SafeArea(
child: LoadingManager(
isLoading: _isLoading,
isFailedLoading: false,
stateCode: 200,
onRefresh: () async {},
child: SingleChildScrollView(
padding: EdgeInsets.all(12 * AppStyle.getScaleFactor(context)),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Center(
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Text(
"Transfer Asset",
style: Theme.of(context).textTheme.headline5.copyWith(color: Theme.of(context).primaryColor, fontSize: 28, fontWeight: FontWeight.bold),
),
child: Column(
children: [
SingleChildScrollView(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
16.height,
PickAsset(
device: _pickedAsset,
onPickAsset: (asset) {
_pickedAsset = asset;
setState(() {});
},
),
16.height,
context.translation.receiverDetails.heading5(context),
8.height,
AppTextFormField(
controller: _receiverNameController,
labelText: context.translation.receiverName,
validator: (text) => Validator.hasValue(text) ? null : context.translation.requiredField,
onSaved: (text) {},
),
8.height,
SingleItemDropDownMenu<Site, SiteProvider>(
context: context,
title: context.translation.destinationSite,
initialValue: _assetDestination?.site,
onSelect: (value) {
_assetDestination.site = value;
_assetDestination.building = null;
_assetDestination.floor = null;
_assetDestination.department = null;
setState(() {});
},
),
8.height,
SingleItemDropDownMenu<Building, NullableLoadingProvider>(
context: context,
title: context.translation.building,
initialValue: _assetDestination?.building,
enabled: _assetDestination?.site?.buildings?.isNotEmpty ?? false,
staticData: _assetDestination?.site?.buildings ?? [],
onSelect: (value) {
_assetDestination?.building = value;
_assetDestination?.floor = null;
_assetDestination?.department = null;
setState(() {});
},
),
8.height,
SingleItemDropDownMenu<Floor, NullableLoadingProvider>(
context: context,
title: context.translation.floor,
initialValue: _assetDestination?.floor,
enabled: _assetDestination?.building?.floors?.isNotEmpty ?? false,
staticData: _assetDestination?.building?.floors ?? [],
onSelect: (value) {
_assetDestination?.floor = value;
_assetDestination?.department = null;
setState(() {});
},
),
8.height,
SingleItemDropDownMenu<Department, NullableLoadingProvider>(
context: context,
title: context.translation.department,
initialValue: _assetDestination?.department,
enabled: _assetDestination?.floor?.departments?.isNotEmpty ?? false,
staticData: _assetDestination?.floor?.departments ?? [],
onSelect: (value) {
_assetDestination?.department = value;
},
),
),
// const SizedBox(height: 8,),
// ASubTitle(_subtitle.title),
// if(_validate && _formModel.title == null || _formModel.title?.isEmpty == true)
// ASubTitle(_subtitle.requiredWord,color: Colors.red,),
// const SizedBox(height: 4,),
// ATextFormField(
// initialValue: _formModel?.title,
// textAlign: TextAlign.center,
// style: Theme.of(context).textTheme.subtitle1,
// textInputType: TextInputType.text,
// onSaved: (value){
// _formModel.title = value;
// },
// ),
12.height,
const ASubTitle("Asset"),
if (_validate /*&& _formModel.device == null*/)
ASubTitle(
context.translation.requiredWord,
color: Colors.red,
16.height,
context.translation.comments.heading5(context),
8.height,
AppTextFormField(
controller: _commentsController,
labelText: context.translation.comments,
onSaved: (text) {
_transferModel.senderComment = text;
},
),
6.height,
// DeviceButton(
// device: _formModel.device,
// onDevicePick: (device) {
// _formModel.device = device;
// _formModel.sender.client = device.hospital;
// setState(() {});
// },
// ),
// if (_formModel.device != null) 8.height,
// if (_formModel.device != null) AdditionalAssetInfo(title: "Asset Site", value: _formModel.device.hospital?.name),
// if (_formModel.device != null) 4.height,
// if (_formModel.device != null) AdditionalAssetInfo(title: "Asset Department", value: _formModel.device.destDepartmentName),
// if (_formModel.device != null) 4.height,
// if (_formModel.device != null) AdditionalAssetInfo(title: "Asset Floor", value: _formModel.device.destFloor),
// if (_formModel.device != null) 4.height,
// if (_formModel.device != null) AdditionalAssetInfo(title: "Asset Room", value: _formModel.device.destRoom),
// if (_formModel.device != null) 8.height,
// const SizedBox(height: 8,),
// const ASubTitle("Sender Department"),
// if(_validate && _formModel.senderDepartment == null)
// ASubTitle(_subtitle.requiredWord,color: Colors.red,),
// const SizedBox(height: 4,),
// DepartmentButton(
// department: _formModel.senderDepartment,
// onDepartmentPick: (department){
// _formModel.senderDepartment = department;
// setState(() {});
// },
// ),
// 12.height,
// const ASubTitle("Destination Client"),
// if (_validate && _formModel.receiver.client == null)
// ASubTitle(
// _subtitle.requiredWord,
// color: Colors.red,
// ),
// 6.height,
// HospitalButton(
// hospital: _formModel.receiver.client,
// onHospitalPick: (hospital) {
// _formModel.receiver.client = hospital;
// setState(() {});
// },
// ),
// 12.height,
// const ASubTitle("Destination Department"),
// if (_validate && _formModel.receiver.department == null)
// ASubTitle(
// _subtitle.requiredWord,
// color: Colors.red,
// ),
// 6.height,
// DepartmentButton(
// department: _formModel.receiver.department,
// onDepartmentPick: (department) {
// _formModel.receiver.department = department;
// setState(() {});
// },
// ),
const SizedBox(
height: 4,
),
Divider(
color: Theme.of(context).colorScheme.primary,
),
const SizedBox(height: 8),
const ASubTitle("Destination"),
const SizedBox(
height: 4,
),
HospitalAutoCompleteField(
initialValue: _deviceTransferProvider.hospital?.name,
// onSave: (value){
// _search.hospital = value;
// },
onSearch: (value) {
_deviceTransferProvider.hospital = value;
_deviceTransferProvider.building = null;
_deviceTransferProvider.floor = null;
_deviceTransferProvider.department = null;
// _formModel.receiver.client = value;
setState(() {});
},
),
const SizedBox(
height: 8,
),
BuildingTypeMenu(
initialValue: _deviceTransferProvider?.building,
building: _deviceTransferProvider?.hospital?.buildings,
onSelect: (status) {
_deviceTransferProvider.building = status;
setState(() {});
},
),
const SizedBox(height: 8),
FloorTypeMenu(
initialValue: _deviceTransferProvider?.floor,
floors: _deviceTransferProvider?.building?.floors,
onSelect: (status) {
_deviceTransferProvider.floor = status;
setState(() {});
},
),
const SizedBox(height: 8),
DepartmentTypeMenu(
initialValue: _deviceTransferProvider?.department,
departments: _deviceTransferProvider?.floor?.departments,
onSelect: (status) {
_deviceTransferProvider.department = status;
// _formModel.receiver.department = Department(id: status.id, name: status.name);
setState(() {});
},
),
const SizedBox(height: 8),
const ASubTitle("Room"),
const SizedBox(
height: 4,
),
ATextFormField(
textAlign: TextAlign.center,
controller: _requestedQuantityController,
style: Theme.of(context).textTheme.subtitle1,
validator: (value) => Validator.isNumeric(value) ? null : "allow numbers only",
textInputType: TextInputType.number,
onSaved: (value) {
_deviceTransferProvider.room = value;
},
),
12.height,
AButton(
text: context.translation.submit,
onPressed: _onSubmit,
),
const SizedBox(
height: 100,
)
],
),
),
),
100.height,
],
),
).expanded,
AppFilledButton(label: context.translation.submitRequest, maxWidth: true, onPressed: _onSubmit)
],
).paddingOnly(start: 16, end: 16, bottom: 24),
),
),
);
}
}
class AdditionalAssetInfo extends StatelessWidget {
final String title, value;
const AdditionalAssetInfo({@required this.title, @required this.value, Key key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
ASubTitle(title ?? ""),
Container(
width: double.infinity,
alignment: Alignment.center,
padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 16),
decoration: BoxDecoration(
color: AColors.inputFieldBackgroundColor,
border: Border.all(
color: const Color(0xffefefef),
),
borderRadius: BorderRadius.circular(AppStyle.borderRadius * AppStyle.getScaleFactor(context)),
),
child: ASubTitle(value ?? ""),
),
],
);
}
}

@ -22,7 +22,6 @@ import 'package:test_sa/views/widgets/loaders/app_loading.dart';
import 'package:test_sa/views/widgets/status/service_request/service_request_defect_types_mune.dart';
import '../../../controllers/api_routes/http_status_manger.dart';
import '../../../controllers/localization/localization.dart';
import '../../../controllers/providers/api/status_drop_down/report/service_report_fault_description_provider.dart';
import '../../widgets/app_text_form_field.dart';
import '../../widgets/buttons/app_back_button.dart';

@ -12,7 +12,6 @@ import 'package:test_sa/controllers/providers/settings/setting_provider.dart';
import 'package:test_sa/extensions/int_extensions.dart';
import 'package:test_sa/extensions/widget_extensions.dart';
import 'package:test_sa/new_views/pages/new_gas_refill_request_page.dart';
import 'package:test_sa/new_views/pages/new_transfer_request_page.dart';
import 'package:test_sa/views/app_style/colors.dart';
import 'package:test_sa/views/app_style/sizing.dart';
import 'package:test_sa/views/pages/device_transfer/track_device_transfer.dart';
@ -27,6 +26,7 @@ import 'package:test_sa/views/widgets/drawer/drawer_item.dart';
import 'package:url_launcher/url_launcher.dart';
import '../../widgets/land_page/land_page_item.dart';
import '../device_transfer/request_device_transfer.dart';
import 'requests/requests_page.dart';
@Deprecated("Use the page which is inside the [new_views/pages/land_page] folder")
@ -147,7 +147,7 @@ class _LandPageState extends State<LandPage> {
mainAxisSpacing: 12,
childAspectRatio: 1,
children: [
/// enable this condition when the nurse account works
/// todo [zaid] : enable this condition when the nurse account works
// if (_userProvider.user != null && _userProvider.user.type == UsersTypes.normal_user)
LandPageItem(
// text: _subtitle.newServiceRequest,
@ -182,7 +182,7 @@ class _LandPageState extends State<LandPage> {
// Navigator.of(context).pushNamed(PreventiveMaintenanceVisitsPage.id);
// },
// ),
/// enable this condition when the nurse account works
/// todo [zaid] : enable this condition when the nurse account works
// if (_userProvider?.user != null && _userProvider?.user?.type != UsersTypes.engineer)
LandPageItem(
text: "Request Gas Refill",
@ -203,8 +203,7 @@ class _LandPageState extends State<LandPage> {
text: "Transfer Asset",
icon: FontAwesomeIcons.rightLeft,
onPressed: () {
// Navigator.of(context).pushNamed(RequestDeviceTransfer.id);
Navigator.of(context).pushNamed(NewTransferRequestPage.routeName);
Navigator.of(context).pushNamed(RequestDeviceTransfer.id);
},
),
LandPageItem(
@ -215,7 +214,7 @@ class _LandPageState extends State<LandPage> {
},
),
/// enable this condition when the nurse account works
/// todo [zaid] : enable this condition when the nurse account works
// if (_userProvider?.user != null && _userProvider?.user?.type != UsersTypes.normal_user)
LandPageItem(
text: "Create Sub Work Order",

@ -1,11 +1,7 @@
import 'dart:convert';
import 'dart:io';
import 'package:file_picker/file_picker.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:fluttertoast/fluttertoast.dart';
import 'package:image_picker/image_picker.dart';
import 'package:provider/provider.dart';
import 'package:test_sa/controllers/providers/api/service_requests_provider.dart';
import 'package:test_sa/controllers/providers/api/user_provider.dart';
@ -16,19 +12,20 @@ import 'package:test_sa/extensions/text_extensions.dart';
import 'package:test_sa/extensions/widget_extensions.dart';
import 'package:test_sa/models/service_request/service_request.dart';
import 'package:test_sa/new_views/common_widgets/app_filled_button.dart';
import 'package:test_sa/providers/service_request_providers/requested_through_provider.dart';
import 'package:test_sa/views/widgets/equipment/pick_asset.dart';
import 'package:test_sa/views/widgets/images/multi_image_picker.dart';
import 'package:test_sa/views/widgets/loaders/loading_manager.dart';
import 'package:test_sa/views/widgets/sound/record_sound.dart';
import '../../../../models/lookup.dart';
import '../../../../new_views/app_style/app_color.dart';
import '../../../../new_views/common_widgets/app_dashed_button.dart';
import '../../../../new_views/common_widgets/app_lazy_loading.dart';
import '../../../../new_views/common_widgets/app_text_form_field.dart';
import '../../../../new_views/common_widgets/default_app_bar.dart';
import '../../../../new_views/common_widgets/single_item_drop_down_menu.dart';
import '../../../../providers/service_request_providers/equipment_status_provider.dart';
import '../../../../providers/service_request_providers/priority_provider.dart';
import '../../../../providers/service_request_providers/type_of_request_provider.dart';
class CreateServiceRequestPage extends StatefulWidget {
static const String id = "/create-request";
@ -156,8 +153,30 @@ class CreateServiceRequestPageState extends State<CreateServiceRequestPage> {
},
),
8.height,
AppDashedButton(title: _serviceRequest.devicePhotos?.first?.split("/")?.last ?? context.translation.attachImage, onPressed: _attachImage),
16.height,
Consumer<RequestedThroughProvider>(builder: (context, snapshot, _) {
return SingleItemDropDownMenu<Lookup, RequestedThroughProvider>(
context: context,
enabled: false,
title: context.translation.requestedThrough,
initialValue: snapshot.items?.firstWhere((element) => element.id == 375, orElse: () => null),
);
}),
8.height,
SingleItemDropDownMenu<Lookup, TypeOfRequestProvider>(
context: context,
title: context.translation.typeOfRequest,
initialValue: _serviceRequest?.type,
onSelect: (value) {
_serviceRequest.type = value;
},
),
8.height,
MultiFilesPicker(
label: context.translation.attachImage,
onlyImages: true,
files: _deviceImages,
),
((_serviceRequest.devicePhotos?.isNotEmpty ?? false) ? 16 : 8).height,
Align(
alignment: AlignmentDirectional.centerStart,
child: context.translation.callComments.heading5(context),
@ -191,58 +210,8 @@ class CreateServiceRequestPageState extends State<CreateServiceRequestPage> {
);
}
_attachImage() async {
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) {
_serviceRequest.devicePhotos ??= [];
_serviceRequest.devicePhotos?.clear();
_serviceRequest.devicePhotos?.add(pickedFile.path);
setState(() {});
}
}
_fromFilePicker() async {
FilePickerResult result = await FilePicker.platform.pickFiles(
type: FileType.custom,
allowedExtensions: ['jpg', 'jpeg', 'png', 'pdf', 'doc', 'docx', 'xlsx', 'pptx'],
);
if (result?.files?.first != null) {
_serviceRequest.devicePhotos ??= [];
_serviceRequest.devicePhotos?.clear();
_serviceRequest.devicePhotos?.add(result?.files?.first?.path);
setState(() {});
}
}
Future<void> _submit() async {
_serviceRequest?.requestedThrough = Provider.of<RequestedThroughProvider>(context, listen: false).items?.firstWhere((element) => element.id == 375, orElse: () => null);
if (_formKey.currentState.validate() && await _serviceRequest.validateNewRequest(context)) {
_formKey.currentState.save();
_serviceRequest.devicePhotos = _deviceImages.map((e) => _isLocalUrl(e.path) ? "${e.path.split("/").last}|${base64Encode(e.readAsBytesSync())}" : e.path).toList();
@ -252,19 +221,12 @@ class CreateServiceRequestPageState extends State<CreateServiceRequestPage> {
_serviceRequest.audio = "${file.path.split("/").last}|${base64Encode(file.readAsBytesSync())}";
}
}
showDialog(context: context, barrierDismissible: false, builder: (context) => const AppLazyLoading());
int status = await _serviceRequestsProvider.createRequest(
await _serviceRequestsProvider.createRequest(
context: context,
user: _userProvider.user,
host: _settingProvider.host,
serviceRequest: _serviceRequest,
);
Navigator.of(context);
if (status >= 200 && status < 300) {
Fluttertoast.showToast(msg: context.translation.successfulRequestMessage);
Navigator.pop(context);
} else {
Fluttertoast.showToast(msg: context.translation.failedRequestMessage);
}
}
}
}

@ -5,7 +5,6 @@ import 'package:flutter/material.dart';
import 'package:fluttertoast/fluttertoast.dart';
import 'package:provider/provider.dart';
import 'package:test_sa/controllers/api_routes/http_status_manger.dart';
import 'package:test_sa/controllers/localization/localization.dart';
import 'package:test_sa/controllers/providers/api/service_requests_provider.dart';
import 'package:test_sa/controllers/providers/api/status_drop_down/report/service_report_last_calls_provider.dart';
import 'package:test_sa/controllers/providers/api/user_provider.dart';
@ -17,7 +16,6 @@ import 'package:test_sa/models/engineer.dart';
import 'package:test_sa/models/part.dart';
import 'package:test_sa/models/service_report.dart';
import 'package:test_sa/models/service_request/service_request.dart';
import 'package:test_sa/models/subtitle.dart';
import 'package:test_sa/views/app_style/colors.dart';
import 'package:test_sa/views/app_style/sizing.dart';
import 'package:test_sa/views/widgets/app_text_form_field.dart';

@ -5,7 +5,6 @@ import 'package:flutter/material.dart';
import 'package:fluttertoast/fluttertoast.dart';
import 'package:provider/provider.dart';
import 'package:test_sa/controllers/api_routes/http_status_manger.dart';
import 'package:test_sa/controllers/localization/localization.dart';
import 'package:test_sa/controllers/providers/api/service_requests_provider.dart';
import 'package:test_sa/controllers/providers/api/status_drop_down/report/service_report_last_calls_provider.dart';
import 'package:test_sa/controllers/providers/api/status_drop_down/report/service_types_provider.dart';
@ -18,7 +17,6 @@ import 'package:test_sa/models/engineer.dart';
import 'package:test_sa/models/part.dart';
import 'package:test_sa/models/service_report.dart';
import 'package:test_sa/models/service_request/service_request.dart';
import 'package:test_sa/models/subtitle.dart';
import 'package:test_sa/views/app_style/colors.dart';
import 'package:test_sa/views/app_style/sizing.dart';
import 'package:test_sa/views/widgets/app_text_form_field.dart';

@ -1,6 +1,5 @@
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:test_sa/controllers/localization/localization.dart';
import 'package:test_sa/extensions/context_extension.dart';
import 'package:test_sa/views/app_style/colors.dart';
import 'package:test_sa/views/widgets/loaders/image_loader.dart';

@ -5,170 +5,74 @@ import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:fluttertoast/fluttertoast.dart';
import 'package:image_picker/image_picker.dart';
import 'package:test_sa/controllers/localization/localization.dart';
import 'package:test_sa/extensions/context_extension.dart';
import 'package:test_sa/extensions/int_extensions.dart';
import 'package:test_sa/models/subtitle.dart';
import 'package:test_sa/views/app_style/colors.dart';
import 'package:test_sa/views/app_style/sizing.dart';
import 'package:test_sa/views/widgets/buttons/app_flat_button.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import '../../../new_views/common_widgets/app_dashed_button.dart';
import 'multi_image_picker_item.dart';
class MultiFilesPicker extends StatefulWidget {
final String label;
final bool error;
final List<File> files;
final bool enabled;
final bool enabled, onlyImages;
const MultiFilesPicker({Key key, this.files, this.label, this.error = false, this.enabled = true}) : super(key: key);
const MultiFilesPicker({Key key, this.files, this.label, this.error = false, this.enabled = true, this.onlyImages = false}) : super(key: key);
@override
_MultiFilesPickerState createState() => _MultiFilesPickerState();
State<MultiFilesPicker> createState() => _MultiFilesPickerState();
}
class _MultiFilesPickerState extends State<MultiFilesPicker> with TickerProviderStateMixin {
Size _size;
class _MultiFilesPickerState extends State<MultiFilesPicker> {
@override
Widget build(BuildContext context) {
_size = MediaQuery.of(context).size;
return (widget.enabled == false && (widget.files?.isEmpty ?? false))
? const SizedBox()
: Container(
padding: const EdgeInsets.all(12),
decoration: BoxDecoration(
color: const Color(0xfff5f5f5),
border: Border.all(
color: const Color(0xffefefef),
),
borderRadius: BorderRadius.circular(AppStyle.borderRadius * AppStyle.getScaleFactor(context)),
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
// SizedBox(height: 8 * AppStyle.getScaleFactor(context),),
Row(
children: [
Expanded(
child: Text(
widget.label ?? context.translation.images,
style: Theme.of(context).textTheme.headline6.copyWith(
fontSize: 14,
),
textScaleFactor: AppStyle.getScaleFactor(context),
),
),
if (widget.enabled)
AFlatButton(
text: context.translation.add,
onPressed: widget.enabled
? () {
// onImagePick(_subtitle);
onFilePicker(context.translation);
}
: null,
),
],
),
12.height,
AnimatedSize(
duration: const Duration(milliseconds: 400),
child: !widget.error
? const SizedBox.shrink()
: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
context.translation.imagesRequired,
style: Theme.of(context).textTheme.headline6.copyWith(
fontSize: 14,
color: AColors.red,
),
textScaleFactor: AppStyle.getScaleFactor(context),
),
SizedBox(
height: 8 * AppStyle.getScaleFactor(context),
),
],
),
),
AnimatedSwitcher(
duration: const Duration(milliseconds: 400),
child: Container(
key: ValueKey(widget.files.length),
width: _size.width,
height: 200 * AppStyle.getScaleFactor(context),
padding: EdgeInsets.all(
8 * AppStyle.getScaleFactor(context),
),
alignment: Alignment.topLeft,
decoration: BoxDecoration(
border: Border.all(color: Theme.of(context).primaryColor, width: 2),
borderRadius: BorderRadius.circular(8 * AppStyle.getScaleFactor(context)),
),
child: widget.files.isEmpty && widget.enabled
? MaterialButton(
onPressed: widget.enabled
? () {
// onImagePick(_subtitle);
onFilePicker(context.translation);
}
: null,
child: Center(
child: Icon(
Icons.file_upload,
size: 48 * AppStyle.getScaleFactor(context),
color: Theme.of(context).primaryColor,
)),
)
: GridView.count(
crossAxisCount: 2,
//_size.width ~/ 80,
scrollDirection: Axis.horizontal,
mainAxisSpacing: 10,
crossAxisSpacing: 10,
children: List.generate(widget.files.length, (index) {
File _image = widget.files[index];
return MultiFilesPickerItem(
file: _image,
enabled: widget.enabled,
onRemoveTap: (image) {
if (!widget.enabled) {
return;
}
widget.files.remove(image);
setState(() {});
},
);
}),
),
),
),
],
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
AppDashedButton(title: widget.label, onPressed: (widget.enabled == false) ? () {} : onFilePicker),
16.height,
if (widget.files?.isNotEmpty ?? false)
Wrap(
spacing: 8.toScreenWidth,
children: List.generate(
widget.files.length,
(index) {
File image = widget.files[index];
return MultiFilesPickerItem(
file: image,
enabled: widget.enabled,
onRemoveTap: (image) {
if (!widget.enabled) {
return;
}
widget.files.remove(image);
setState(() {});
},
);
},
),
);
),
],
);
}
fromFilePicker(AppLocalizations subtitle) async {
fromFilePicker() async {
FilePickerResult result = await FilePicker.platform.pickFiles(
type: FileType.custom,
allowMultiple: true,
allowedExtensions: ['jpg', 'jpeg', 'png', 'pdf', 'doc', 'docx', 'xlsx', 'pptx'],
allowedExtensions: widget.onlyImages ? ['jpg', 'jpeg', 'png'] : ['jpg', 'jpeg', 'png', 'pdf', 'doc', 'docx', 'xlsx', 'pptx'],
);
if (result != null) {
for (var path in result.paths) {
widget.files.insert(0, File(path));
widget.files.add(File(path));
}
setState(() {});
}
}
onFilePicker(AppLocalizations subtitle) async {
onFilePicker() async {
if (widget.files.length >= 5) {
Fluttertoast.showToast(msg: subtitle.maxImagesNumberIs5);
Fluttertoast.showToast(msg: context.translation.maxImagesNumberIs5);
return;
}
ImageSource source = await showDialog(
@ -176,21 +80,21 @@ class _MultiFilesPickerState extends State<MultiFilesPicker> with TickerProvider
builder: (dialogContext) => CupertinoAlertDialog(
actions: <Widget>[
TextButton(
child: Text(subtitle.pickFromCamera),
child: Text(context.translation.pickFromCamera),
onPressed: () {
Navigator.of(dialogContext).pop(ImageSource.camera);
},
),
TextButton(
child: Text(subtitle.pickFromGallery),
child: Text(context.translation.pickFromGallery),
onPressed: () {
Navigator.of(dialogContext).pop(ImageSource.gallery);
},
),
TextButton(
child: Text(subtitle.pickFromFiles),
child: Text(context.translation.pickFromFiles),
onPressed: () async {
await fromFilePicker(subtitle);
await fromFilePicker();
Navigator.pop(context);
},
),
@ -204,7 +108,7 @@ class _MultiFilesPickerState extends State<MultiFilesPicker> with TickerProvider
if (pickedFile != null) {
File fileImage = File(pickedFile.path);
if (fileImage != null) {
widget.files.insert(0, fileImage);
widget.files.add(fileImage);
setState(() {});
}
}

@ -3,10 +3,12 @@ import 'dart:io';
import 'package:flutter/material.dart';
import 'package:fluttertoast/fluttertoast.dart';
import 'package:open_file/open_file.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/views/app_style/colors.dart';
import 'package:test_sa/views/app_style/sizing.dart';
import 'package:test_sa/views/widgets/buttons/app_back_button.dart';
import 'package:test_sa/new_views/app_style/app_color.dart';
import 'package:test_sa/new_views/common_widgets/default_app_bar.dart';
import 'package:test_sa/views/widgets/loaders/image_loader.dart';
import 'package:url_launcher/url_launcher.dart';
@ -22,72 +24,64 @@ class MultiFilesPickerItem extends StatelessWidget {
var isImage = file.path.split(".").last.toLowerCase() == "png" || file.path.split(".").last.toLowerCase() == "jpg" || file.path.split(".").last.toLowerCase() == "jpeg";
var isPdf = file.path.split(".").last.toLowerCase() == "pdf";
var isExcel = file.path.split(".").last.toLowerCase() == "xlsx";
return Container(
width: 80 * AppStyle.getScaleFactor(context),
height: 80 * AppStyle.getScaleFactor(context),
decoration: BoxDecoration(
boxShadow: [BoxShadow(color: isImage ? Colors.black38 : AColors.cyan.withOpacity(0.5), blurRadius: 2)],
image: DecorationImage(
image: isImage
? (_isLocalUrl(file.path) ? FileImage(file) : NetworkImage(file.path))
: AssetImage("assets/images/${isPdf ? "pdf" : isExcel ? "excel" : "doc"}.png"),
fit: BoxFit.cover,
),
borderRadius: BorderRadius.circular(8),
),
child: MaterialButton(
padding: EdgeInsets.zero,
onPressed: () async {
if (isImage) {
Navigator.of(context).push(
MaterialPageRoute(
builder: (_) => Scaffold(
body: SafeArea(
child: Stack(
children: [
InteractiveViewer(
child: _isLocalUrl(file.path)
? Image.file(file)
: ImageLoader(
url: file.path,
boxFit: BoxFit.cover,
))
.center,
const ABackButton(),
],
),
),
),
return SizedBox(
width: 54.toScreenWidth,
height: 51.toScreenWidth,
child: Stack(
alignment: AlignmentDirectional.topEnd,
children: [
Container(
margin: EdgeInsetsDirectional.only(top: 4.toScreenHeight, end: 6.toScreenWidth),
decoration: BoxDecoration(
border: Border.all(width: 1, color: context.isDark ? AppColor.neutral30 : AppColor.neutral30),
image: DecorationImage(
image: isImage
? (_isLocalUrl(file.path) ? FileImage(file) : NetworkImage(file.path))
: AssetImage("assets/images/${isPdf ? "pdf" : isExcel ? "excel" : "doc"}.png"),
fit: BoxFit.cover,
),
);
} else if (_isLocalUrl(file.path)) {
OpenFile.open(file.path);
} else {
if (!await launchUrl(Uri.parse(file.path), mode: LaunchMode.externalApplication)) {
Fluttertoast.showToast(msg: "UnExpected Error with file.");
throw Exception('Could not launch ');
}
}
},
child: enabled
? Align(
alignment: Alignment.topRight,
child: IconButton(
padding: const EdgeInsets.all(2.0),
icon: Container(
padding: const EdgeInsets.all(1),
decoration: BoxDecoration(color: Theme.of(context).scaffoldBackgroundColor.withOpacity(.3), borderRadius: BorderRadius.circular(8)),
child: const Icon(
Icons.remove_circle,
color: AColors.red,
borderRadius: BorderRadius.circular(8),
),
child: MaterialButton(
padding: EdgeInsets.zero,
onPressed: () async {
if (isImage) {
Navigator.of(context).push(
MaterialPageRoute(
builder: (_) => Scaffold(
appBar: const DefaultAppBar(),
body: SafeArea(
child: InteractiveViewer(
child: _isLocalUrl(file.path)
? Image.file(file)
: ImageLoader(
url: file.path,
boxFit: BoxFit.cover,
),
).center,
),
),
),
),
onPressed: () {
onRemoveTap(file);
},
),
)
: const SizedBox(),
);
} else if (_isLocalUrl(file.path)) {
OpenFile.open(file.path);
} else {
if (!await launchUrl(Uri.parse(file.path), mode: LaunchMode.externalApplication)) {
Fluttertoast.showToast(msg: "UnExpected Error with file.");
throw Exception('Could not launch ');
}
}
},
),
),
if (enabled)
InkWell(
child: "remove".toSvgAsset(width: 16),
onTap: () {
onRemoveTap(file);
},
)
],
),
);
}

@ -2,7 +2,6 @@ import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:test_sa/controllers/localization/localization.dart';
import 'package:test_sa/controllers/providers/api/user_provider.dart';
import 'package:test_sa/extensions/context_extension.dart';
import 'package:test_sa/models/pantry/pentry.dart';

Loading…
Cancel
Save