Merge branch 'zaid-development' into 'master'
Restructuring Project Files & Supporting Null Safety See merge request haroon6138/cloudsolutions-atoms!3merge-requests/3/merge
commit
6e4c740568
@ -1,40 +0,0 @@
|
||||
import 'package:test_sa/models/subtitle.dart';
|
||||
import 'package:meta/meta.dart';
|
||||
|
||||
class HttpStatusManger{
|
||||
static String getStatusMessage({
|
||||
@required int status,
|
||||
@required Subtitle subtitle,
|
||||
String messageFor400,
|
||||
String messageFor200,
|
||||
}){
|
||||
if(status == null)
|
||||
// no status code - code error no need for subtitle
|
||||
return "careful null status";
|
||||
if(status == -1)
|
||||
// client's request in process
|
||||
return subtitle.currentlyServiceNotAvailable;
|
||||
if(status == -2){
|
||||
// client's request in process
|
||||
return subtitle.waitUntilYourRequestComplete;
|
||||
}else if(status >= 200 && status < 300){
|
||||
// client's request was successfully received
|
||||
return messageFor200 ?? subtitle.requestCompleteSuccessfully;
|
||||
} else if(status >= 400 && status < 500){
|
||||
// client's request have error
|
||||
switch(status){
|
||||
case 400:
|
||||
return messageFor400 ?? subtitle.failedToCompleteRequest;
|
||||
default:
|
||||
return subtitle.failedToCompleteRequest;
|
||||
}
|
||||
} else if(status >= 500){
|
||||
// server error
|
||||
return subtitle.currentlyServiceNotAvailable;
|
||||
} else {
|
||||
// no error match so return default error
|
||||
return subtitle.failedToCompleteRequest;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@ -1,172 +0,0 @@
|
||||
import 'dart:convert';
|
||||
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:http/http.dart';
|
||||
import 'package:test_sa/controllers/api_routes/urls.dart';
|
||||
import 'package:test_sa/models/gas_refill/gas_refill_model.dart';
|
||||
import 'package:test_sa/models/user.dart';
|
||||
|
||||
class GasRefillProvider extends ChangeNotifier{
|
||||
|
||||
// number of items call in each request
|
||||
final pageItemNumber = 50;
|
||||
|
||||
//reset provider data
|
||||
void reset(){
|
||||
items = null;
|
||||
nextPage = true;
|
||||
stateCode = null;
|
||||
}
|
||||
|
||||
// state code of current request to defied error message
|
||||
// like 400 customer request failed
|
||||
// 500 service not available
|
||||
int stateCode;
|
||||
|
||||
// true if there is next page in product list and false if not
|
||||
bool nextPage = true;
|
||||
|
||||
// list of user requests
|
||||
List<GasRefillModel> items;
|
||||
|
||||
// when requests in-process _loading = true
|
||||
// done _loading = true
|
||||
// failed _loading = false
|
||||
bool isLoading;
|
||||
|
||||
/// return -2 if request in progress
|
||||
/// return -1 if error happen when sending request
|
||||
/// 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> getRequests ({
|
||||
@required String host,
|
||||
@required User user,
|
||||
}) async {
|
||||
if(isLoading == true)
|
||||
return -2;
|
||||
isLoading = true;
|
||||
Response response;
|
||||
try{
|
||||
response = await get(
|
||||
Uri.parse(
|
||||
"$host${URLs.getGasRefill}?uid=${user.id}"
|
||||
"&token=${user.token}&page=${(items?.length ?? 0) ~/pageItemNumber}"
|
||||
),
|
||||
headers: {
|
||||
"Content-Type":"application/json; charset=utf-8"
|
||||
}
|
||||
);
|
||||
stateCode = response.statusCode;
|
||||
if(stateCode >= 200 && stateCode < 300) {
|
||||
// client's request was successfully received
|
||||
List requestsListJson = json.decode(utf8.decode(response.bodyBytes));
|
||||
List<GasRefillModel> itemsPage = requestsListJson.map(
|
||||
(request) => GasRefillModel.fromJson(request)).toList();
|
||||
items ??= [];
|
||||
items.addAll(itemsPage);
|
||||
if(itemsPage.length == pageItemNumber){
|
||||
nextPage = true;
|
||||
}else{
|
||||
nextPage = false;
|
||||
}
|
||||
}
|
||||
isLoading = false;
|
||||
notifyListeners();
|
||||
return response.statusCode;
|
||||
|
||||
} catch(error) {
|
||||
isLoading = false;
|
||||
stateCode = -1;
|
||||
notifyListeners();
|
||||
return -1;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Future<int> createModel ({
|
||||
@required String host,
|
||||
@required User user,
|
||||
@required GasRefillModel model,
|
||||
}) async {
|
||||
Map<String,dynamic> body = {
|
||||
"uid": user.id.toString(),
|
||||
"token": user.token ?? "",
|
||||
"title": model.title ?? "",
|
||||
"status": "0",//model.status.value.toString(),
|
||||
};
|
||||
|
||||
body["details"] = jsonEncode(model.details.map((model) => {
|
||||
"type": model.type.id?.toString(),
|
||||
"size": model.cylinderSize?.id.toString(),
|
||||
"requsted_qty": model.requestedQuantity.toString(),
|
||||
}).toList());
|
||||
|
||||
Response response;
|
||||
try{
|
||||
response = await post(
|
||||
Uri.parse(
|
||||
host+URLs.requestGasRefill),
|
||||
body: body,
|
||||
);
|
||||
|
||||
stateCode = response.statusCode;
|
||||
if(response.statusCode >= 200 && response.statusCode < 300) {
|
||||
if(items != null) {
|
||||
items.insert(
|
||||
0,
|
||||
GasRefillModel.fromJson(
|
||||
json.decode(utf8.decode(response.bodyBytes))[0]
|
||||
)
|
||||
);
|
||||
notifyListeners();
|
||||
}
|
||||
}
|
||||
return response.statusCode;
|
||||
|
||||
} catch(error) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Future<int> updateModel ({
|
||||
@required String host,
|
||||
@required User user,
|
||||
@required GasRefillModel oldModel,
|
||||
@required GasRefillModel newModel,
|
||||
}) async {
|
||||
Map<String,dynamic> body = {
|
||||
"uid": user.id.toString(),
|
||||
"token": user.token ?? "",
|
||||
"title": newModel.title ?? "",
|
||||
"status": newModel.status.id.toString(),
|
||||
};
|
||||
|
||||
body["details"] = jsonEncode(newModel.details.map((model) => {
|
||||
"type": model.type.id.toString(),
|
||||
"size": model.cylinderSize.id.toString(),
|
||||
"requsted_qty": model.requestedQuantity.toString(),
|
||||
"deliverd_qty": model.deliveredQuantity.toString(),
|
||||
}).toList());
|
||||
|
||||
Response response;
|
||||
try{
|
||||
response = await post(
|
||||
Uri.parse("$host${URLs.updateGasRefill}/${newModel.id}"),
|
||||
body: body,
|
||||
);
|
||||
|
||||
stateCode = response.statusCode;
|
||||
if(response.statusCode >= 200 && response.statusCode < 300) {
|
||||
oldModel.fromGasRefillModel(newModel);
|
||||
notifyListeners();
|
||||
}
|
||||
return response.statusCode;
|
||||
|
||||
} catch(error) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@ -1,422 +0,0 @@
|
||||
import 'dart:convert';
|
||||
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:http/http.dart';
|
||||
import 'package:test_sa/controllers/api_routes/urls.dart';
|
||||
import 'package:test_sa/controllers/http_status_manger/http_status_manger.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:test_sa/models/subtitle.dart';
|
||||
import 'package:test_sa/models/timer_model.dart';
|
||||
import 'package:test_sa/models/user.dart';
|
||||
|
||||
class ServiceRequestsProvider extends ChangeNotifier{
|
||||
|
||||
// number of items call in each request
|
||||
final pageItemNumber = 50;
|
||||
|
||||
//reset provider data
|
||||
void reset(){
|
||||
serviceRequests = null;
|
||||
nextPage = true;
|
||||
stateCode = null;
|
||||
}
|
||||
|
||||
// state code of current request to defied error message
|
||||
// like 400 customer request failed
|
||||
// 500 service not available
|
||||
int stateCode;
|
||||
|
||||
// true if there is next page in product list and false if not
|
||||
bool nextPage = true;
|
||||
|
||||
// list of user requests
|
||||
List<ServiceRequest> serviceRequests;
|
||||
|
||||
// when requests in-process _loading = true
|
||||
// done _loading = true
|
||||
// failed _loading = false
|
||||
bool isLoading;
|
||||
|
||||
ServiceRequestSearch search = ServiceRequestSearch();
|
||||
|
||||
/// return -2 if request in progress
|
||||
/// return -1 if error happen when sending request
|
||||
/// 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> getRequests ({
|
||||
@required String host,
|
||||
@required User user,
|
||||
@required String hospitalId,
|
||||
}) async {
|
||||
if(isLoading == true)
|
||||
return -2;
|
||||
isLoading = true;
|
||||
Response response;
|
||||
try{
|
||||
response = await get(
|
||||
Uri.parse(
|
||||
host+URLs.getServiceRequests
|
||||
+"?uid=${user.id}"
|
||||
+(hospitalId == null? "" :"&client_nid=$hospitalId")
|
||||
+"&token=${user.token}"
|
||||
"&page=${(serviceRequests?.length ?? 0) ~/pageItemNumber}"
|
||||
+search?.toSearchString() ?? ""
|
||||
),
|
||||
headers: {
|
||||
"Content-Type":"application/json; charset=utf-8"
|
||||
}
|
||||
);
|
||||
stateCode = response.statusCode;
|
||||
if(response.statusCode >= 200 && response.statusCode < 300) {
|
||||
// client's request was successfully received
|
||||
List requestsListJson = json.decode(utf8.decode(response.bodyBytes).replaceAll("\\", ""));
|
||||
List<ServiceRequest> _serviceRequestsPage = requestsListJson.map(
|
||||
(request) => ServiceRequest.fromJson(request)).toList();
|
||||
if(serviceRequests == null)
|
||||
serviceRequests = [];
|
||||
serviceRequests.addAll(_serviceRequestsPage);
|
||||
if(_serviceRequestsPage.length == pageItemNumber){
|
||||
nextPage = true;
|
||||
}else{
|
||||
nextPage = false;
|
||||
}
|
||||
}
|
||||
isLoading = false;
|
||||
notifyListeners();
|
||||
return response.statusCode;
|
||||
|
||||
} catch(error) {
|
||||
isLoading = false;
|
||||
stateCode = -1;
|
||||
notifyListeners();
|
||||
return -1;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Future<ServiceRequest> getSingleServiceRequest({
|
||||
@required String requestId,
|
||||
@required String host,
|
||||
@required User user,
|
||||
@required Subtitle subtitle,
|
||||
}) async {
|
||||
String userData = '';
|
||||
if(user != null){
|
||||
userData += "&uid="+user.id;
|
||||
userData += "&token="+user.token;
|
||||
}
|
||||
|
||||
Response response;
|
||||
try{
|
||||
response = await get(
|
||||
Uri.parse(
|
||||
host+URLs.getSingleServiceRequest
|
||||
+'?call_nid=$requestId'
|
||||
'$userData',)
|
||||
);
|
||||
}catch(error){
|
||||
throw(HttpStatusManger.getStatusMessage(
|
||||
status: -1, subtitle: subtitle));
|
||||
}
|
||||
|
||||
// If the call to the server was successful, parse the JSON.
|
||||
if (response.statusCode >= 200 && response.statusCode < 300){
|
||||
// If the call to the server was successful, parse the JSON.
|
||||
List jsonList = json.decode(utf8.decode(response.bodyBytes).replaceAll("\\", ""));
|
||||
List<ServiceRequest> _requests = jsonList.map((i) => ServiceRequest.fromJson(i)).toList();
|
||||
return _requests[0];
|
||||
}else{
|
||||
throw(HttpStatusManger.getStatusMessage(
|
||||
status: response.statusCode, subtitle: subtitle));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Future<int> createRequest ({
|
||||
@required String host,
|
||||
@required User user,
|
||||
@required ServiceRequest serviceRequest,
|
||||
}) async {
|
||||
|
||||
var body = {
|
||||
"uid": user.id,
|
||||
"token": user.token ?? "",
|
||||
"sn_id": serviceRequest.deviceId ?? "",
|
||||
"date": (DateTime.now().millisecondsSinceEpoch).toString(),
|
||||
"client": user.hospital.id ?? '',
|
||||
"complaint": serviceRequest.maintenanceIssue,
|
||||
"image": json.encode(serviceRequest.devicePhotos),
|
||||
"priority": (serviceRequest.priority?.id).toString(),
|
||||
"defect_types": (serviceRequest.defectType?.id).toString(),
|
||||
};
|
||||
if(serviceRequest.audio != null){
|
||||
body["audio"] = serviceRequest.audio;
|
||||
}
|
||||
Response response;
|
||||
try{
|
||||
response = await post(
|
||||
Uri.parse(
|
||||
host+URLs.createRequest),
|
||||
body: body,
|
||||
);
|
||||
stateCode = response.statusCode;
|
||||
if(response.statusCode >= 200 && response.statusCode < 300) {
|
||||
if(serviceRequests != null)
|
||||
serviceRequests.insert(
|
||||
0,
|
||||
ServiceRequest.fromJson(
|
||||
json.decode(utf8.decode(response.bodyBytes))[0]
|
||||
)
|
||||
);
|
||||
notifyListeners();
|
||||
}
|
||||
return response.statusCode;
|
||||
|
||||
} catch(error) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Future<int> createIssueReport ({
|
||||
@required String host,
|
||||
@required User user,
|
||||
@required Issue issue,
|
||||
}) async {
|
||||
Response response;
|
||||
Map<String,String> body = issue.toMap();
|
||||
body["uid"] = user.id;
|
||||
body["token"] = user.token;
|
||||
try{
|
||||
response = await post(
|
||||
Uri.parse(host+URLs.createReport),
|
||||
body: body,
|
||||
);
|
||||
|
||||
stateCode = response.statusCode;
|
||||
if(response.statusCode >= 200 && response.statusCode < 300) {
|
||||
|
||||
}
|
||||
return response.statusCode;
|
||||
|
||||
} catch(error) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Future<int> updateDate ({
|
||||
@required String host,
|
||||
@required User user,
|
||||
@required String newDate,
|
||||
@required Lookup employee,
|
||||
@required ServiceRequest request,
|
||||
}) async {
|
||||
Response response;
|
||||
Map<String,String> body = {};
|
||||
body["uid"] = user.id;
|
||||
body["token"] = user.token;
|
||||
body["nid"] = request.id;
|
||||
if(newDate != null) body["date"] = newDate;
|
||||
if(employee != null) body["ass_emp"] = employee.id.toString();
|
||||
try{
|
||||
response = await post(
|
||||
Uri.parse(
|
||||
host+URLs.updateRequestDate),
|
||||
body: body,
|
||||
);
|
||||
stateCode = response.statusCode;
|
||||
if(response.statusCode >= 200 && response.statusCode < 300) {
|
||||
request.engineerName = employee.label;
|
||||
notifyListeners();
|
||||
}
|
||||
return response.statusCode;
|
||||
|
||||
} catch(error) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Future<int> createServiceReport ({
|
||||
@required String host,
|
||||
@required User user,
|
||||
@required ServiceReport report,
|
||||
@required ServiceRequest request,
|
||||
}) async {
|
||||
Response response;
|
||||
Map<String,String> body = report.toMap();
|
||||
body["uid"] = user.id;
|
||||
body["token"] = user.token;
|
||||
body["job_id"] = request.id;
|
||||
try{
|
||||
response = await post(
|
||||
Uri.parse(
|
||||
host+URLs.createServiceReport),
|
||||
body: body,
|
||||
);
|
||||
|
||||
stateCode = response.statusCode;
|
||||
if(response.statusCode >= 200 && response.statusCode < 300) {
|
||||
reset();
|
||||
notifyListeners();
|
||||
}
|
||||
return response.statusCode;
|
||||
|
||||
} catch(error) {
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Future<int> createDuplicatedReport ({
|
||||
@required String host,
|
||||
@required User user,
|
||||
@required ServiceRequest request,
|
||||
}) async {
|
||||
Response response;
|
||||
String userData = '';
|
||||
if(user != null){
|
||||
userData += "&uid="+user.id;
|
||||
userData += "&token="+user.token;
|
||||
}
|
||||
|
||||
try{
|
||||
response = await get(
|
||||
Uri.parse(
|
||||
host+URLs.createDuplicatedReport
|
||||
+"?nid=${request.id}"
|
||||
+userData),
|
||||
);
|
||||
|
||||
stateCode = response.statusCode;
|
||||
|
||||
if(response.statusCode >= 200 && response.statusCode < 300) {
|
||||
reset();
|
||||
notifyListeners();
|
||||
}
|
||||
return response.statusCode;
|
||||
|
||||
} catch(error) {
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Future<int> updateServiceReport ({
|
||||
@required String host,
|
||||
@required User user,
|
||||
@required ServiceReport report,
|
||||
@required ServiceRequest request,
|
||||
}) async {
|
||||
Response response;
|
||||
Map<String,String> body = report.toMap();
|
||||
body["uid"] = user.id;
|
||||
body["token"] = user.token;
|
||||
body["job_id"] = request.id;
|
||||
body["report_id"] = request.reportID;
|
||||
try{
|
||||
response = await post(
|
||||
Uri.parse(
|
||||
host+URLs.updateServiceReport),
|
||||
body: body,
|
||||
);
|
||||
stateCode = response.statusCode;
|
||||
|
||||
if(response.statusCode >= 200 && response.statusCode < 300) {
|
||||
reset();
|
||||
notifyListeners();
|
||||
}
|
||||
return response.statusCode;
|
||||
|
||||
} catch(error) {
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Future<int> updateServiceReportTimer ({
|
||||
@required String host,
|
||||
@required User user,
|
||||
@required TimerModel timer,
|
||||
@required ServiceRequest request,
|
||||
}) async {
|
||||
Response response;
|
||||
Map<String,String> body = {};
|
||||
body["uid"] = user.id;
|
||||
body["token"] = user.token;
|
||||
body["job_id"] = request.id;
|
||||
body["start_time"] = (timer.startAt.millisecondsSinceEpoch / 1000).toStringAsFixed(0);
|
||||
body["end_time"] = (timer.endAt.millisecondsSinceEpoch / 1000).toStringAsFixed(0);
|
||||
body["working_hours"] = (timer.durationInSecond / 60 / 60).toStringAsFixed(5);
|
||||
body["report_id"] = request.reportID;
|
||||
try{
|
||||
response = await post(
|
||||
Uri.parse(
|
||||
host+URLs.updateServiceReport),
|
||||
body: body,
|
||||
);
|
||||
//stateCode = response.statusCode;
|
||||
|
||||
if(response.statusCode >= 200 && response.statusCode < 300) {
|
||||
// reset();
|
||||
// notifyListeners();
|
||||
}
|
||||
return response.statusCode;
|
||||
|
||||
} catch(error) {
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Future<ServiceReport> getSingleServiceReport({
|
||||
@required String reportId,
|
||||
@required String host,
|
||||
@required User user,
|
||||
@required Subtitle subtitle,
|
||||
}) async {
|
||||
String userData = '';
|
||||
if(user != null){
|
||||
userData += "&uid="+user.id;
|
||||
userData += "&token="+user.token;
|
||||
}
|
||||
|
||||
Response response;
|
||||
try{
|
||||
|
||||
response = await get(
|
||||
Uri.parse(
|
||||
host+URLs.getServiceReport
|
||||
+'?report_id=$reportId'
|
||||
'$userData',)
|
||||
);
|
||||
|
||||
}catch(error){
|
||||
throw(HttpStatusManger.getStatusMessage(
|
||||
status: -1, subtitle: subtitle));
|
||||
}
|
||||
|
||||
// If the call to the server was successful, parse the JSON.
|
||||
if (response.statusCode >= 200 && response.statusCode < 300){
|
||||
// If the call to the server was successful, parse the JSON.
|
||||
return ServiceReport.fromJson(
|
||||
json.decode(utf8.decode(response.bodyBytes)),reportId);
|
||||
}else{
|
||||
throw(HttpStatusManger.getStatusMessage(
|
||||
status: response.statusCode, subtitle: subtitle));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@ -0,0 +1,17 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_localizations/flutter_localizations.dart';
|
||||
import 'package:test_sa/core/enums.dart' show SupportedLanguagesEnum;
|
||||
|
||||
class AppLocalizations {
|
||||
AppLocalizations._();
|
||||
|
||||
static List<Locale> supportedLocales =
|
||||
SupportedLanguagesEnum.values.map((e) => Locale(e.name)).toList();
|
||||
|
||||
static List<LocalizationsDelegate> get delegates => const [
|
||||
// AppLocalization.delegate,
|
||||
GlobalMaterialLocalizations.delegate,
|
||||
GlobalWidgetsLocalizations.delegate,
|
||||
GlobalCupertinoLocalizations.delegate,
|
||||
];
|
||||
}
|
||||
@ -0,0 +1,29 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:test_sa/screens/login_screen/login_screen.dart';
|
||||
import 'package:test_sa/screens/splash_screen/splash_screen.dart';
|
||||
|
||||
Map<String, Widget Function(BuildContext)> appRoutes = {
|
||||
SplashScreen.routeName: (_) => const SplashScreen(),
|
||||
LoginScreen.routeName: (_) => const LoginScreen(),
|
||||
// LandPage.routeName: (_) => const LandPage(),
|
||||
// Register.routeName: (_) => Register(),
|
||||
// ProfilePage.routeName: (_) => ProfilePage(),
|
||||
// ReportIssuesPage.routeName: (_) => const ReportIssuesPage(),
|
||||
// RequestGasRefill.routeName: (_) => const RequestGasRefill(),
|
||||
// CreateRequestPage.routeName: (_) => CreateRequestPage(),
|
||||
// SingleHospitalPicker.routeName: (_) => SingleHospitalPicker(),
|
||||
// SingleDevicePicker.routeName: (_) => SingleDevicePicker(),
|
||||
// SingleDepartmentPicker.routeName: (_) => SingleDepartmentPicker(),
|
||||
// ServiceRequestsPage.routeName: (_) => ServiceRequestsPage(),
|
||||
// NotificationsPage.routeName: (_) => NotificationsPage(),
|
||||
// FutureRequestServiceDetails.routeName: (_) =>
|
||||
// FutureRequestServiceDetails(),
|
||||
// PreventiveMaintenanceVisitsPage.routeName: (_) =>
|
||||
// PreventiveMaintenanceVisitsPage(),
|
||||
// RegularVisitsPage.routeName: (_) => RegularVisitsPage(),
|
||||
// TrackGasRefillPage.routeName: (_) => const TrackGasRefillPage(),
|
||||
// RequestDeviceTransfer.routeName: (_) =>
|
||||
// const RequestDeviceTransfer(),
|
||||
// TrackDeviceTransferPage.routeName: (_) =>
|
||||
// const TrackDeviceTransferPage(),
|
||||
};
|
||||
@ -0,0 +1,20 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:test_sa/core/constants/app_colors.dart';
|
||||
|
||||
class AppTheme {
|
||||
AppTheme._();
|
||||
|
||||
static get theme => ThemeData(
|
||||
fontFamily: "Poppins",
|
||||
canvasColor: AppColors.primaryColor,
|
||||
scaffoldBackgroundColor: AppColors.scaffoldBackgroundColor,
|
||||
primaryColor: AppColors.primaryColor,
|
||||
indicatorColor: AppColors.primaryColor,
|
||||
colorScheme: const ColorScheme.light(
|
||||
primary: AppColors.primaryColor,
|
||||
onPrimary: Colors.white,
|
||||
secondary: AppColors.secondaryColor,
|
||||
onSecondary: Colors.white,
|
||||
),
|
||||
);
|
||||
}
|
||||
@ -0,0 +1,66 @@
|
||||
class ApiConstants {
|
||||
ApiConstants._();
|
||||
static const host2 = "http://194.163.164.213/atoms/api";
|
||||
static const host1 = "https://atoms.hmg.com/api";
|
||||
|
||||
// API Routes
|
||||
static const login = "/handle/user/login"; // post
|
||||
static const register = "/handle/create/user"; // post
|
||||
static const updateProfile = "/update/user/profile"; // post
|
||||
static const getHospitals = "/handle/return/all/clients"; // get
|
||||
static const getDepartments = "/handle/return/all/departments"; // get
|
||||
static const getEquipment = "/handle/return/all/client/equipments"; // get ?client=208051
|
||||
static const getServiceRequests = "/return/user/calls"; // get
|
||||
|
||||
static const getPreventiveMaintenanceVisits = "/return/user/calibrations"; // get
|
||||
static const updatePreventiveMaintenanceVisits = "/update/user/calibrations"; // get
|
||||
|
||||
static const getRegularVisits = "/return/user/ppm"; // get
|
||||
static const updateRegularVisits = "/update/user/ppm"; // get
|
||||
|
||||
static const getSingleServiceRequest = "/return/call/information"; // get
|
||||
static const getNotifications = "/return/user/notification"; // get
|
||||
static const getRecentNotifications = "/return/user/recent/notification"; // get
|
||||
static const createRequest = "/handle/create/request"; // get
|
||||
static const createReport = "/handle/create/report/issue"; // get
|
||||
static const updateRequestDate = "/handle/update/request"; // get
|
||||
|
||||
// service report
|
||||
static const createServiceReport = "/handle/create/service/report"; // get
|
||||
static const updateServiceReport = "/handle/update/service/report"; // get
|
||||
static const getServiceReport = "/handle/view/service/report"; // get
|
||||
static const createDuplicatedReport = "/handle/duplicate/request"; // get
|
||||
|
||||
static const getServiceReportReasons = "/return/service/report/reasons"; // get
|
||||
static const getServiceReportTypes = "/return/service/report/type"; // get
|
||||
static const getServiceReportStatus = "/return/service/report/status"; // get
|
||||
static const getServiceReportLastCalls = "/return/call/last/situation"; // get
|
||||
static const getServiceTypes = "/return/service/type"; // get
|
||||
static const getPartNumber = "/handle/return/all/parts"; // get
|
||||
static const getServiceReportPriority = "/return/call/priority/list"; // get
|
||||
static const getServiceReportDefectTypes = "/return/call/defect/type/list"; // get
|
||||
|
||||
//gas refill
|
||||
static const getGasTypes = "/return/gas/refill/types"; // get
|
||||
static const getGasCylinderSize = "/return/gas/refill/size/cylinder"; // get
|
||||
static const getGasStatus = "/return/gas/refill/status"; // get
|
||||
static const requestGasRefill = "/create/gas/refill"; // get
|
||||
static const updateGasRefill = "/update/gas/refill/"; // get
|
||||
static const getGasRefill = "/search/gas/refill"; // get
|
||||
|
||||
//device transfer
|
||||
static const requestDeviceTransfer = "/create/transfer/asset"; // get
|
||||
static const updateDeviceTransfer = "/update/transfer/asset"; // get
|
||||
static const getDeviceTransfer = "/search/transfer/asset"; // get
|
||||
|
||||
// employee
|
||||
static const getEmployees = "/return/assigned/employee"; // get
|
||||
// pentry
|
||||
static const getPentry = "/return/pentry/details"; // get
|
||||
static const updatePentry = "/update/pentry/details"; // get
|
||||
static const getPentryTaskStatus = "/return/pentry/task/status"; // get
|
||||
static const getPentryVisitStatus = "/return/pentry/visit/status/list"; // get
|
||||
static const getPentryStatus = "/return/pentry/status/list"; // get
|
||||
// contacts
|
||||
static const getPentryContacts = "/handle/return/all/contacts"; // get
|
||||
}
|
||||
@ -0,0 +1,50 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class AppColors {
|
||||
AppColors._();
|
||||
|
||||
static const Color white = Color(0xffffffff);
|
||||
static const Color black = Color(0xff000000);
|
||||
static const Color grey3A = Color(0xff2e303a);
|
||||
static const Color grey = Color(0xffe1e7e7);
|
||||
static const green = Colors.green;
|
||||
static const Color orange = Colors.orange;
|
||||
static const Color deepOrange = Colors.deepOrangeAccent;
|
||||
static const Color red = Colors.red;
|
||||
static const Color deepRed = Color(0xFFD32F2F);
|
||||
static const Color scaffoldBackgroundColor = Color(0xffffffff);
|
||||
static const Color secondaryColor = Color(0xff111427);
|
||||
static const Color primaryColor = Color(0xff5bb0da);
|
||||
static const Color cyan = Color(0xff4A8DB7);
|
||||
static const Color onPrimaryColor = Color(0xffffffff);
|
||||
static const Color inputFieldBackgroundColor = Color(0xfff5f5f5);
|
||||
static const Color greyEF = Color(0xffEFEFEF);
|
||||
|
||||
static Color getRequestStatusColor(int id) {
|
||||
switch (id) {
|
||||
case 4:
|
||||
return deepRed;
|
||||
case 6:
|
||||
return green;
|
||||
case 5:
|
||||
return orange;
|
||||
case 8:
|
||||
return green;
|
||||
case 9:
|
||||
return orange;
|
||||
default:
|
||||
return grey;
|
||||
}
|
||||
}
|
||||
|
||||
static Color getGasStatusColor(int id) {
|
||||
switch (id) {
|
||||
case 0:
|
||||
return orange;
|
||||
case 1:
|
||||
return green;
|
||||
default:
|
||||
return grey;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,20 @@
|
||||
enum SupportedLanguagesEnum { ar, en }
|
||||
|
||||
enum RequestMethod { get, post, put, delete }
|
||||
|
||||
enum ApiExceptionsEnum {
|
||||
badRequest(10),
|
||||
unauthorized(10),
|
||||
forbidden(10),
|
||||
notFound(10),
|
||||
internalServerError(10),
|
||||
upgradeRequired(10),
|
||||
badResponseFormat(10),
|
||||
other(10),
|
||||
timeout(10),
|
||||
unknown(10);
|
||||
|
||||
final int statusCode;
|
||||
|
||||
const ApiExceptionsEnum(this.statusCode);
|
||||
}
|
||||
@ -0,0 +1,3 @@
|
||||
import 'package:flutter/widgets.dart';
|
||||
|
||||
extension ContextExtension on BuildContext {}
|
||||
@ -0,0 +1,16 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:test_sa/core/constants/app_colors.dart';
|
||||
|
||||
extension NumExtension on num {
|
||||
Widget get height => SizedBox(height: toDouble());
|
||||
|
||||
Widget get width => SizedBox(width: toDouble());
|
||||
|
||||
Widget get divider => Divider(
|
||||
height: toDouble(),
|
||||
thickness: toDouble(),
|
||||
color: AppColors.greyEF,
|
||||
);
|
||||
|
||||
Widget get makeItSquare => SizedBox(width: toDouble(), height: toDouble());
|
||||
}
|
||||
@ -0,0 +1 @@
|
||||
extension StringExtension on String {}
|
||||
@ -0,0 +1,3 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
extension WidgetExtension on Widget {}
|
||||
@ -0,0 +1,46 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:test_sa/providers/settings_provider.dart';
|
||||
|
||||
class ProviderScope extends StatelessWidget {
|
||||
final Widget child;
|
||||
|
||||
const ProviderScope({required this.child, Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return MultiProvider(
|
||||
providers: [
|
||||
ChangeNotifierProvider(create: (_) => SettingsProvider()),
|
||||
// ChangeNotifierProvider(create: (_) => UserProvider()),
|
||||
// ChangeNotifierProvider(create: (_) => HospitalsProvider()),
|
||||
// ChangeNotifierProvider(create: (_) => DevicesProvider()),
|
||||
// ChangeNotifierProvider(create: (_) => ServiceRequestsProvider()),
|
||||
// ChangeNotifierProvider(create: (_) => DepartmentsProvider()),
|
||||
// ChangeNotifierProvider(create: (_) => NotificationsProvider()),
|
||||
// ChangeNotifierProvider(
|
||||
// create: (_) => PreventiveMaintenanceVisitsProvider()),
|
||||
// ChangeNotifierProvider(create: (_) => RegularVisitsProvider()),
|
||||
// ChangeNotifierProvider(create: (_) => PartsProvider()),
|
||||
// ChangeNotifierProvider(create: (_) => ServiceReportReasonsProvider()),
|
||||
// ChangeNotifierProvider(create: (_) => ServiceReportStatusProvider()),
|
||||
// ChangeNotifierProvider(create: (_) => ServiceReportTypesProvider()),
|
||||
// ChangeNotifierProvider(create: (_) => ServiceStatusProvider()),
|
||||
// ChangeNotifierProvider(create: (_) => ServiceReportLastCallsProvider()),
|
||||
// ChangeNotifierProvider(create: (_) => GasCylinderSizesProvider()),
|
||||
// ChangeNotifierProvider(create: (_) => GasStatusProvider()),
|
||||
// ChangeNotifierProvider(create: (_) => GasTypesProvider()),
|
||||
// ChangeNotifierProvider(create: (_) => GasRefillProvider()),
|
||||
// ChangeNotifierProvider(create: (_) => DeviceTransferProvider()),
|
||||
// ChangeNotifierProvider(create: (_) => EmployeesProvider()),
|
||||
// ChangeNotifierProvider(create: (_) => PentryTaskStatusProvider()),
|
||||
// ChangeNotifierProvider(create: (_) => PentryVisitStatusProvider()),
|
||||
// ChangeNotifierProvider(create: (_) => PentryStatusProvider()),
|
||||
// ChangeNotifierProvider(create: (_) => ServiceRequestPriorityProvider()),
|
||||
// ChangeNotifierProvider(
|
||||
// create: (_) => ServiceRequestDefectTypesProvider()),
|
||||
],
|
||||
child: child,
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,57 @@
|
||||
import 'dart:convert';
|
||||
|
||||
import 'package:http/http.dart' as http;
|
||||
import 'package:test_sa/core/enums.dart';
|
||||
|
||||
class ApiClient {
|
||||
final String baseUrl, endPoint;
|
||||
final RequestMethod requestMethod;
|
||||
|
||||
ApiClient.request({
|
||||
required this.baseUrl,
|
||||
required this.endPoint,
|
||||
required this.requestMethod,
|
||||
});
|
||||
|
||||
Future<Map<String, dynamic>> execute({
|
||||
Map<String, String>? headers,
|
||||
Map<String, dynamic>? queryParameters,
|
||||
Object? body,
|
||||
}) async {
|
||||
final url = Uri.tryParse(baseUrl + endPoint);
|
||||
if (url != null) {
|
||||
late http.Response response;
|
||||
switch (requestMethod) {
|
||||
case RequestMethod.get:
|
||||
response = await http.get(url, headers: headers);
|
||||
break;
|
||||
case RequestMethod.post:
|
||||
response = await http.post(url, headers: headers, body: body);
|
||||
break;
|
||||
case RequestMethod.put:
|
||||
response = await http.put(url, headers: headers, body: body);
|
||||
break;
|
||||
case RequestMethod.delete:
|
||||
response = await http.delete(url, headers: headers, body: body);
|
||||
break;
|
||||
}
|
||||
return await _handleResponse(response);
|
||||
} else {
|
||||
throw ApiExceptionsEnum.other;
|
||||
}
|
||||
}
|
||||
|
||||
Future<Map<String, dynamic>> _handleResponse(http.Response response) {
|
||||
print('status code ${response.statusCode} : ${response.request?.url}');
|
||||
if (response.statusCode == 200) {
|
||||
return jsonDecode(response.body);
|
||||
} else if (response.statusCode == 401) {
|
||||
throw ApiExceptionsEnum.unauthorized;
|
||||
} else if (response.statusCode == 400) {
|
||||
throw ApiExceptionsEnum.badRequest;
|
||||
} else if (response.statusCode == 500) {
|
||||
throw ApiExceptionsEnum.internalServerError;
|
||||
}
|
||||
throw ApiExceptionsEnum.unknown;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,18 @@
|
||||
import 'package:test_sa/core/enums.dart';
|
||||
import 'package:test_sa/data/api/api_client.dart';
|
||||
import 'package:test_sa/data/models/user_model.dart';
|
||||
|
||||
class UserService {
|
||||
static UserService instance = UserService._internal();
|
||||
|
||||
UserService._internal();
|
||||
|
||||
Future<UserModel> getUser() async {
|
||||
final response = await ApiClient.request(
|
||||
baseUrl: 'baseUrl',
|
||||
endPoint: 'endPoint',
|
||||
requestMethod: RequestMethod.get,
|
||||
).execute();
|
||||
return UserModel.fromJson(response);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,7 @@
|
||||
class UserModel {
|
||||
UserModel();
|
||||
|
||||
factory UserModel.fromJson(Map<String, dynamic> json) {
|
||||
return UserModel();
|
||||
}
|
||||
}
|
||||
@ -1,50 +0,0 @@
|
||||
import 'package:test_sa/models/device/device.dart';
|
||||
import 'package:test_sa/models/device/device_transfer_info.dart';
|
||||
|
||||
class DeviceTransfer{
|
||||
String id;
|
||||
String userId;
|
||||
String title;
|
||||
Device device;
|
||||
DeviceTransferInfo sender;
|
||||
DeviceTransferInfo receiver;
|
||||
|
||||
DeviceTransfer({
|
||||
this.id,
|
||||
this.device,
|
||||
this.title,
|
||||
this.userId,
|
||||
this.sender,
|
||||
this.receiver,
|
||||
});
|
||||
|
||||
bool validate(){
|
||||
if(device == null) return false;
|
||||
return receiver.validate();
|
||||
}
|
||||
|
||||
fromDeviceTransfer(DeviceTransfer old){
|
||||
id = old.id;
|
||||
title = old.title;
|
||||
userId = old.userId;
|
||||
device = Device.fromDevice(old.device);
|
||||
final sender = DeviceTransferInfo();
|
||||
sender.fromDetails(old.sender);
|
||||
this.sender = sender;
|
||||
final receiver = DeviceTransferInfo();
|
||||
receiver.fromDetails(old.receiver);
|
||||
this.receiver = receiver;
|
||||
}
|
||||
|
||||
factory DeviceTransfer.fromJson(Map<String,dynamic> parsedJson){
|
||||
return DeviceTransfer(
|
||||
id: parsedJson["id"],
|
||||
title: parsedJson["title"],
|
||||
userId: parsedJson["uid"],
|
||||
device: Device.fromJson(parsedJson["eq_sn"]),
|
||||
sender: DeviceTransferInfo.fromJson(parsedJson,"sender_"),
|
||||
receiver: DeviceTransferInfo.fromJson(parsedJson,"receiver_"),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,72 +0,0 @@
|
||||
import 'package:test_sa/models/department.dart';
|
||||
import 'package:test_sa/models/hospital.dart';
|
||||
import 'package:test_sa/models/lookup.dart';
|
||||
|
||||
class DeviceTransferInfo{
|
||||
String userId;
|
||||
String comment;
|
||||
Hospital client;
|
||||
Department department;
|
||||
String workingHours;
|
||||
String travelingHours;
|
||||
String name;
|
||||
String signature;
|
||||
Lookup status;
|
||||
|
||||
DeviceTransferInfo({
|
||||
this.userId,
|
||||
this.comment,
|
||||
this.department,
|
||||
this.client,
|
||||
this.name,
|
||||
this.travelingHours,
|
||||
this.workingHours,
|
||||
this.signature,
|
||||
this.status,
|
||||
});
|
||||
|
||||
Map<String,String>toJson(bool isSender){
|
||||
Map<String,String> body = {};
|
||||
final baseKey = isSender ? "sender_" : "receiver_";
|
||||
|
||||
if(comment != null && comment.isNotEmpty) body["${baseKey}comment"] = comment;
|
||||
if(workingHours != null && workingHours.isNotEmpty) body["${baseKey}working_hours"] = workingHours;
|
||||
if(travelingHours != null && travelingHours.isNotEmpty) body["${baseKey}travel_hours"] = comment;
|
||||
if(status != null) body["${baseKey}status"] = status.id.toString();
|
||||
if(signature != null && signature.isNotEmpty) body["${baseKey}image"] = signature;
|
||||
return body;
|
||||
}
|
||||
|
||||
bool validate(){
|
||||
if(client == null) return false;
|
||||
if(department == null) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
fromDetails(DeviceTransferInfo old,{bool withSignature = true}){
|
||||
userId = old.userId;
|
||||
name = old.name;
|
||||
client = Hospital.fromHospital(old.client);
|
||||
department = Department.fromDepartment(old.department);
|
||||
workingHours = old.workingHours;
|
||||
travelingHours = old.travelingHours;
|
||||
comment = old.comment;
|
||||
if(withSignature) signature = old.signature;
|
||||
status = old.status;
|
||||
}
|
||||
|
||||
factory DeviceTransferInfo.fromJson(Map<String,dynamic> parsedJson,String key){
|
||||
return DeviceTransferInfo(
|
||||
workingHours: parsedJson["${key}working_hours"],
|
||||
travelingHours: parsedJson["${key}travel_hours"],
|
||||
name: parsedJson["${key}name"],
|
||||
signature: parsedJson["${key}image"],
|
||||
userId: parsedJson["${key}id"],
|
||||
comment: parsedJson["${key}comment"],
|
||||
client: Hospital.fromJson(parsedJson["${key}client"]),
|
||||
department: Department.fromJson(parsedJson["${key}department"]),
|
||||
status: Lookup.fromJson(parsedJson["${key}status"]),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,43 +0,0 @@
|
||||
import 'package:test_sa/models/lookup.dart';
|
||||
|
||||
class GasRefillDetails{
|
||||
Lookup type;
|
||||
Lookup cylinderSize;
|
||||
int requestedQuantity;
|
||||
int deliveredQuantity;
|
||||
|
||||
GasRefillDetails({
|
||||
this.type,
|
||||
this.cylinderSize,
|
||||
this.requestedQuantity,
|
||||
this.deliveredQuantity,
|
||||
});
|
||||
|
||||
bool validate(){
|
||||
//if(cylinderSize == null) return false;
|
||||
if(type == null) return false;
|
||||
if(requestedQuantity == null) return false;
|
||||
return true;
|
||||
}
|
||||
factory GasRefillDetails.fromJson(Map<String,dynamic> parsedJson){
|
||||
return GasRefillDetails(
|
||||
type: Lookup.fromJson(parsedJson["type"]),
|
||||
|
||||
cylinderSize: Lookup.fromJson(parsedJson["size"]),
|
||||
requestedQuantity: parsedJson["requsted_qty"] == null
|
||||
? 0 : int.tryParse(parsedJson["requsted_qty"].toString()) ?? 0,
|
||||
deliveredQuantity: parsedJson["deliverd_qty"] == null
|
||||
? 0 : int.tryParse(parsedJson["deliverd_qty"].toString()) ?? 0,
|
||||
);
|
||||
}
|
||||
|
||||
factory GasRefillDetails.fromDetails(GasRefillDetails details){
|
||||
return GasRefillDetails(
|
||||
type: Lookup.fromStatus(details.type),
|
||||
cylinderSize:Lookup.fromStatus(details.cylinderSize),
|
||||
requestedQuantity: details.requestedQuantity,
|
||||
deliveredQuantity: details.deliveredQuantity,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,53 +0,0 @@
|
||||
import 'package:test_sa/models/gas_refill/gas_refill_details.dart';
|
||||
import 'package:test_sa/models/lookup.dart';
|
||||
|
||||
class GasRefillModel{
|
||||
String id;
|
||||
String userId;
|
||||
String clientName;
|
||||
String title;
|
||||
Lookup status;
|
||||
List<GasRefillDetails> details;
|
||||
|
||||
GasRefillModel({
|
||||
this.id,
|
||||
this.userId,
|
||||
this.clientName,
|
||||
this.title,
|
||||
this.status,
|
||||
this.details,
|
||||
});
|
||||
|
||||
bool validate(){
|
||||
if(title == null) return false;
|
||||
if(status == null) return false;
|
||||
if(details == null && details.isEmpty) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
fromGasRefillModel(GasRefillModel model){
|
||||
id = model.id;
|
||||
userId = model.userId;
|
||||
clientName = model.clientName;
|
||||
title = model.title;
|
||||
status = Lookup.fromStatus(model.status);
|
||||
details = model.details.map((e) => GasRefillDetails.fromDetails(e)).toList();
|
||||
}
|
||||
|
||||
factory GasRefillModel.fromJson(Map<String,dynamic> parsedJson){
|
||||
List<GasRefillDetails> details = [];
|
||||
if(parsedJson["details"] != null){
|
||||
List list = parsedJson["details"];
|
||||
details = list.map((e) => GasRefillDetails.fromJson(e)).toList();
|
||||
}
|
||||
return GasRefillModel(
|
||||
id: parsedJson["id"],
|
||||
userId: parsedJson["uid"],
|
||||
title: parsedJson["title"],
|
||||
clientName: parsedJson["client"],
|
||||
status: Lookup.fromJson(parsedJson["status"]),
|
||||
details: details,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,26 +0,0 @@
|
||||
import 'package:test_sa/models/lookup.dart';
|
||||
|
||||
class CalibrationTool{
|
||||
Lookup assetsNumber;
|
||||
DateTime dataOfTesting;
|
||||
|
||||
CalibrationTool({
|
||||
this.assetsNumber,
|
||||
this.dataOfTesting,
|
||||
});
|
||||
|
||||
Map<String, String> toMap() {
|
||||
return {
|
||||
if(assetsNumber != null) 'assetsSN': (assetsNumber?.id).toString(),
|
||||
if(dataOfTesting != null) 'dataOfTesting': (dataOfTesting.millisecondsSinceEpoch ~/ 1000).toString(),
|
||||
};
|
||||
}
|
||||
|
||||
factory CalibrationTool.fromMap(Map<String, dynamic> map) {
|
||||
return CalibrationTool(
|
||||
assetsNumber: Lookup.fromJson(map['assetsSN']),
|
||||
dataOfTesting: map['dataOfTesting'] == null || map['dataOfTesting'] == "" ? null :
|
||||
DateTime.fromMillisecondsSinceEpoch(int.tryParse(map['dataOfTesting']) * 1000),
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -1,41 +0,0 @@
|
||||
import 'package:test_sa/models/lookup.dart';
|
||||
|
||||
class Contact{
|
||||
Lookup title;
|
||||
Lookup contactPerson;
|
||||
String job;
|
||||
String email;
|
||||
String telephone;
|
||||
String landLine;
|
||||
|
||||
Contact({
|
||||
this.title,
|
||||
this.contactPerson,
|
||||
this.job,
|
||||
this.email,
|
||||
this.telephone,
|
||||
this.landLine
|
||||
});
|
||||
|
||||
Map<String, String> toMap() {
|
||||
return {
|
||||
if (title != null) 'title': title.id.toString(),
|
||||
if (contactPerson != null) 'contactPerson': contactPerson.id.toString(),
|
||||
if (job != null) 'job': job,
|
||||
if (email != null) 'email': email,
|
||||
if (telephone != null) 'telephone': telephone,
|
||||
if (landLine != null) 'landLine': landLine,
|
||||
};
|
||||
}
|
||||
|
||||
factory Contact.fromMap(Map<String, dynamic> map) {
|
||||
return Contact(
|
||||
title: map['title'] as Lookup,
|
||||
contactPerson: map['contactPerson'] as Lookup,
|
||||
job: map['job'] as String,
|
||||
email: map['email'] as String,
|
||||
telephone: map['telephone'] as String,
|
||||
landLine: map['landLine'] as String,
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -1,15 +0,0 @@
|
||||
import 'package:test_sa/models/lookup.dart';
|
||||
|
||||
class ContactTitle extends Lookup {
|
||||
ContactTitle({
|
||||
int id,
|
||||
String label
|
||||
}):super(id: id,label: label);
|
||||
|
||||
factory ContactTitle.fromMap(Map<String,dynamic> parsedJson){
|
||||
return ContactTitle(
|
||||
label: parsedJson["value"],
|
||||
id: parsedJson["id"],
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -1,120 +0,0 @@
|
||||
import 'dart:convert';
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:test_sa/models/lookup.dart';
|
||||
import 'package:test_sa/models/pantry/calibration_tools.dart';
|
||||
import 'package:test_sa/models/pantry/pm_kit.dart';
|
||||
import 'package:test_sa/models/pantry/ppm_check_list.dart';
|
||||
import 'package:test_sa/models/timer_model.dart';
|
||||
|
||||
class Pentry{
|
||||
Lookup ppmVisitStatus;
|
||||
Lookup status;
|
||||
TimerModel timer;
|
||||
DateTime actualVisitDate;
|
||||
String travelingHours;
|
||||
String image;
|
||||
File imageFile;
|
||||
// List<Contact> contacts;
|
||||
List<PPMCheckList> ppmCheckLists;
|
||||
List<CalibrationTool> calibrationTools;
|
||||
List<PMKit> pmKits;
|
||||
|
||||
Pentry({
|
||||
this.travelingHours,
|
||||
this.timer,
|
||||
this.status,
|
||||
this.ppmVisitStatus,
|
||||
this.actualVisitDate,
|
||||
this.image,
|
||||
this.imageFile,
|
||||
// this.contacts,
|
||||
this.ppmCheckLists,
|
||||
this.calibrationTools,
|
||||
this.pmKits,
|
||||
});
|
||||
|
||||
bool validate(){
|
||||
if(actualVisitDate == null) return false;
|
||||
if(timer == null && timer.endAt != null) return false;
|
||||
if(ppmVisitStatus == null) return false;
|
||||
//if(status == null) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
Map<String, String> toMap() {
|
||||
Map<String, String> map = {};
|
||||
map["visit_status"] = ppmVisitStatus?.id.toString();
|
||||
if(status != null) map["pentry_status"] = status?.id.toString();
|
||||
if(travelingHours != null) map["traveling_hours"] = travelingHours;
|
||||
if(imageFile != null) map["file_attachement"] = base64Encode(imageFile.readAsBytesSync());
|
||||
map["actual_date"] = (actualVisitDate.millisecondsSinceEpoch / 1000).toStringAsFixed(0);
|
||||
if(timer != null){
|
||||
map["start_date"] = (timer.startAt.millisecondsSinceEpoch / 1000).toStringAsFixed(0);
|
||||
map["end_date"] = ((timer.endAt ?? DateTime.now()).millisecondsSinceEpoch / 1000).toStringAsFixed(0);
|
||||
map["working_hours"] = (timer.durationInSecond / 60 / 60).toStringAsFixed(5);
|
||||
}
|
||||
// if(contacts?.isNotEmpty == true) {
|
||||
// for(int i = 0;i<contacts.length;i++){
|
||||
// contacts[i].toMap().forEach((key, value) {
|
||||
// body["contacts[$i].$key"] = value;
|
||||
// });
|
||||
// }
|
||||
// }
|
||||
map["ppmCheckLists"] = jsonEncode(ppmCheckLists.map((e) => e.toMap()).toList());
|
||||
map["calibrationTools"] = jsonEncode(calibrationTools.map((e) => e.toMap()).toList());
|
||||
map["pmKits"] = jsonEncode(pmKits.map((e) => e.toMap()).toList());
|
||||
return map;
|
||||
}
|
||||
|
||||
factory Pentry.fromMap(Map<String, dynamic> map) {
|
||||
// List<Contact> contacts = [];
|
||||
// if(map['contacts'] != null){
|
||||
// contacts =(map['contacts'] as List<dynamic>)
|
||||
// .map((e) => Contact.fromMap(e as Map<String, dynamic>))
|
||||
// .toList();
|
||||
// }
|
||||
|
||||
List<PMKit> pmKits = [];
|
||||
if(map['pmKits'] != null){
|
||||
pmKits =(map['pmKits'] as List<dynamic>)
|
||||
.map((e) => PMKit.fromMap(e as Map<String, dynamic>))
|
||||
.toList();
|
||||
}
|
||||
|
||||
List<PPMCheckList> ppmCheckLists = [];
|
||||
if(map['ppmCheckLists'] != null){
|
||||
ppmCheckLists =(map['ppmCheckLists'] as List<dynamic>)
|
||||
.map((e) => PPMCheckList.fromMap(e as Map<String, dynamic>))
|
||||
.toList();
|
||||
}
|
||||
|
||||
List<CalibrationTool> calibrationTools = [];
|
||||
if(map['calibrationTools'] != null){
|
||||
calibrationTools =(map['calibrationTools'] as List<dynamic>)
|
||||
.map((e) => CalibrationTool.fromMap(e as Map<String, dynamic>))
|
||||
.toList();
|
||||
}
|
||||
return Pentry(
|
||||
status: Lookup.fromJson(map["pentry_status"]),
|
||||
ppmVisitStatus: Lookup.fromJson(map["visit_status"]),
|
||||
actualVisitDate: getDate(map["actual_date"]),
|
||||
travelingHours: map["traveling_hours"],
|
||||
timer: TimerModel(
|
||||
startAt: getDate(map["start_date"]),
|
||||
endAt: getDate(map["end_date"]),
|
||||
durationInSecond: (int.tryParse(map["working_hours"] ?? "") ?? 0) * 60 *60
|
||||
),
|
||||
// contacts: contacts,
|
||||
ppmCheckLists: ppmCheckLists,
|
||||
calibrationTools: calibrationTools,
|
||||
pmKits: pmKits,
|
||||
);
|
||||
}
|
||||
|
||||
static getDate(String date){
|
||||
return date == null || date.isEmpty
|
||||
? null : DateTime.fromMillisecondsSinceEpoch(int.tryParse(date) * 1000);
|
||||
}
|
||||
}
|
||||
@ -1,46 +0,0 @@
|
||||
class ServiceRequestSearch{
|
||||
String deviceSerialNumber;
|
||||
String deviceName;
|
||||
String hospital;
|
||||
String model;
|
||||
int statusValue;
|
||||
|
||||
|
||||
ServiceRequestSearch({
|
||||
this.deviceSerialNumber,
|
||||
this.statusValue,
|
||||
this.deviceName,
|
||||
this.model,
|
||||
this.hospital,
|
||||
});
|
||||
|
||||
fromSearch(ServiceRequestSearch newSearch){
|
||||
deviceSerialNumber = newSearch.deviceSerialNumber;
|
||||
statusValue = newSearch.statusValue;
|
||||
hospital = newSearch.hospital;
|
||||
model = newSearch.model;
|
||||
}
|
||||
|
||||
String toSearchString(){
|
||||
String _search = "";
|
||||
if(deviceSerialNumber != null && deviceSerialNumber.isNotEmpty){
|
||||
_search += "&sn_id=$deviceSerialNumber";
|
||||
}
|
||||
|
||||
if(statusValue != null){
|
||||
_search += "&status=$statusValue";
|
||||
}
|
||||
|
||||
if(deviceName != null && deviceName.isNotEmpty){
|
||||
_search += "&equipment_en_name=$deviceName";
|
||||
}
|
||||
|
||||
if(hospital != null && hospital.isNotEmpty){
|
||||
_search += "&client=$hospital";
|
||||
}
|
||||
if(model != null && model.isNotEmpty){
|
||||
_search += "&model=$model";
|
||||
}
|
||||
return _search;
|
||||
}
|
||||
}
|
||||
@ -1,45 +0,0 @@
|
||||
|
||||
import 'package:test_sa/models/lookup.dart';
|
||||
import 'package:test_sa/models/visits/visit.dart';
|
||||
|
||||
class VisitsGroup{
|
||||
String userId;
|
||||
String workingHours;
|
||||
String travelingHours;
|
||||
String jobSheetNumber;
|
||||
String image;
|
||||
Lookup status;
|
||||
Lookup taskStatus;
|
||||
DateTime date;
|
||||
List<Visit> visits;
|
||||
|
||||
VisitsGroup({
|
||||
this.userId,
|
||||
this.status,
|
||||
this.date,
|
||||
this.jobSheetNumber,
|
||||
this.travelingHours,
|
||||
this.workingHours,
|
||||
this.visits,
|
||||
this.image,
|
||||
this.taskStatus,
|
||||
});
|
||||
|
||||
Map<String,String> toJson(){
|
||||
Map<String,String> jsonObject = {};
|
||||
jsonObject["nids"] = visits.map((e) => e.id).toList().join(',');
|
||||
if(status != null) jsonObject["status"] = status.id.toString();
|
||||
if(date != null) jsonObject["date"] = date.toString().split(" ").first;
|
||||
if(jobSheetNumber != null && jobSheetNumber.isNotEmpty)
|
||||
jsonObject["job_sheet_no"] = jobSheetNumber;
|
||||
if(travelingHours != null && travelingHours.isNotEmpty)
|
||||
jsonObject["traveling_hours"] = travelingHours;
|
||||
if(workingHours != null && workingHours.isNotEmpty)
|
||||
jsonObject["working_hours"] = workingHours;
|
||||
if(image != null) jsonObject["image"] = image;
|
||||
if(taskStatus != null) jsonObject["task_status"] = taskStatus.id.toString();
|
||||
return jsonObject;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@ -0,0 +1,12 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class SettingsProvider with ChangeNotifier {
|
||||
Locale? _locale;
|
||||
|
||||
Locale? get locale => _locale;
|
||||
|
||||
set locale(Locale? value) {
|
||||
_locale = value;
|
||||
notifyListeners();
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,12 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class LoginScreen extends StatelessWidget {
|
||||
static const routeName = '/loginScreen';
|
||||
|
||||
const LoginScreen({Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return const Scaffold();
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,32 @@
|
||||
import 'package:flare_flutter/flare_actor.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:test_sa/screens/login_screen/login_screen.dart';
|
||||
|
||||
class SplashScreen extends StatelessWidget {
|
||||
static const routeName = "/splashScreen";
|
||||
|
||||
const SplashScreen({Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
backgroundColor: Colors.white,
|
||||
body: Center(
|
||||
child: SizedBox(
|
||||
width: MediaQuery.of(context).size.width / 1.1,
|
||||
child: FlareActor(
|
||||
"assets/rives/atoms_splash.flr",
|
||||
fit: BoxFit.contain,
|
||||
animation: "splash",
|
||||
callback: (animation) async {
|
||||
Navigator.of(context).pushNamed(LoginScreen.routeName);
|
||||
// if (_settingProvider.isLoaded && _settingProvider.user != null) {
|
||||
// _goToUserScreen(_settingProvider.user);
|
||||
// }
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -1,86 +0,0 @@
|
||||
import 'dart:convert';
|
||||
|
||||
import 'package:firebase_core/firebase_core.dart';
|
||||
import 'package:firebase_messaging/firebase_messaging.dart';
|
||||
import 'package:flare_flutter/flare_actor.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:test_sa/controllers/notification/notification_manger.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/models/app_notification.dart';
|
||||
import 'package:test_sa/models/user.dart';
|
||||
import 'package:test_sa/views/pages/user/land_page.dart';
|
||||
|
||||
import 'login.dart';
|
||||
|
||||
class SplashScreen extends StatefulWidget {
|
||||
static const String id = '/splash';
|
||||
const SplashScreen({Key key}) : super(key: key);
|
||||
|
||||
@override
|
||||
State<SplashScreen> createState() => _SplashScreenState();
|
||||
}
|
||||
|
||||
class _SplashScreenState extends State<SplashScreen> {
|
||||
|
||||
SettingProvider _settingProvider;
|
||||
UserProvider _userProvider;
|
||||
|
||||
_goToUserScreen(User user){
|
||||
_userProvider.user = user;
|
||||
// Navigator.of(context).pushNamed(Login.id);
|
||||
Navigator.of(context).pushNamed(LandPage.id);
|
||||
}
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
Firebase.initializeApp();
|
||||
|
||||
NotificationManger.initialisation(
|
||||
(notificationDetails) {
|
||||
AppNotification notification = AppNotification.fromJson(json.decode(notificationDetails.payload));
|
||||
if(notification.path == null || notification.path.isEmpty)
|
||||
return;
|
||||
Navigator.pushNamed(
|
||||
context,
|
||||
notification.path,
|
||||
arguments: notification.requestId
|
||||
);
|
||||
}
|
||||
, (id, title, body, payload) async {
|
||||
});
|
||||
super.initState();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
_settingProvider = Provider.of<SettingProvider>(context,listen: false);
|
||||
_userProvider = Provider.of<UserProvider>(context,listen: false);
|
||||
return Scaffold(
|
||||
backgroundColor: Colors.white,
|
||||
body: Center(
|
||||
child: SizedBox(
|
||||
width: MediaQuery.of(context).size.width/1.1,
|
||||
child: FlareActor(
|
||||
"assets/rives/atoms_splash.flr",
|
||||
fit: BoxFit.contain,
|
||||
animation: "splash",
|
||||
callback: (animation) async {
|
||||
print(await FirebaseMessaging.instance.getToken());
|
||||
Navigator.of(context).pushNamed(Login.id);
|
||||
if(_settingProvider.isLoaded && _settingProvider.user != null){
|
||||
_goToUserScreen(_settingProvider.user);
|
||||
}
|
||||
},
|
||||
),
|
||||
//const Center(child: CircularProgressIndicator())
|
||||
|
||||
// Image.asset("assets/images/logo.png",
|
||||
// fit: BoxFit.contain,
|
||||
// ),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -1,43 +0,0 @@
|
||||
import 'package:test_sa/controllers/localization/localization.dart';
|
||||
import 'package:test_sa/models/app_notification.dart';
|
||||
import 'package:test_sa/models/subtitle.dart';
|
||||
import 'package:test_sa/views/pages/user/requests/future_request_service_details.dart';
|
||||
import 'package:test_sa/views/widgets/loaders/lazy_loading.dart';
|
||||
import 'package:test_sa/views/widgets/loaders/no_item_found.dart';
|
||||
import 'package:test_sa/views/widgets/notifications/notification_item.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
class NotificationsList extends StatelessWidget {
|
||||
final List<AppNotification> notifications;
|
||||
final bool nextPage;
|
||||
final Future<void> Function() onLazyLoad;
|
||||
|
||||
const NotificationsList({Key key, this.notifications, this.nextPage, this.onLazyLoad}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
Subtitle _subtitle = AppLocalization.of(context).subtitle;
|
||||
if(notifications.length == 0){
|
||||
return NoItemFound(message: _subtitle.notificationsNotFound,);
|
||||
}
|
||||
return LazyLoading(
|
||||
nextPage: nextPage,
|
||||
onLazyLoad: onLazyLoad,
|
||||
child: ListView.builder(
|
||||
physics: BouncingScrollPhysics(),
|
||||
itemCount: notifications.length,
|
||||
padding: EdgeInsets.symmetric(horizontal: 16,vertical: 8),
|
||||
itemBuilder: (context,itemIndex){
|
||||
return NotificationItem(
|
||||
notification: notifications[itemIndex],
|
||||
onPressed: (notification){
|
||||
Navigator.of(context).pushNamed(
|
||||
FutureRequestServiceDetails.id,
|
||||
arguments: notification.requestId
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -1,107 +0,0 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:test_sa/views/app_style/sizing.dart';
|
||||
|
||||
class ATextFormField extends StatefulWidget {
|
||||
final Function(String) onSaved;
|
||||
final Function(String) validator;
|
||||
final Function(String) onChange;
|
||||
final bool obscureText;
|
||||
final VoidCallback showPassword;
|
||||
final String hintText;
|
||||
final String labelText;
|
||||
final TextInputType textInputType;
|
||||
final String initialValue;
|
||||
final TextStyle style;
|
||||
final bool enable;
|
||||
final TextAlign textAlign;
|
||||
final FocusNode node;
|
||||
final Widget suffixIcon;
|
||||
final IconData prefixIconData;
|
||||
final double prefixIconSize;
|
||||
final TextEditingController controller;
|
||||
final TextInputAction textInputAction;
|
||||
final VoidCallback onAction;
|
||||
|
||||
const ATextFormField(
|
||||
{Key key,
|
||||
this.onSaved,
|
||||
this.validator,
|
||||
this.node,
|
||||
this.onChange,
|
||||
this.obscureText,
|
||||
this.showPassword,
|
||||
this.hintText,
|
||||
this.labelText,
|
||||
this.textInputType = TextInputType.text,
|
||||
this.initialValue,
|
||||
this.enable = true,
|
||||
this.style,
|
||||
this.textAlign,
|
||||
this.suffixIcon,
|
||||
this.prefixIconData,
|
||||
this.prefixIconSize,
|
||||
this.controller,
|
||||
this.textInputAction,
|
||||
this.onAction})
|
||||
: super(key: key);
|
||||
|
||||
@override
|
||||
State<ATextFormField> createState() => _ATextFormFieldState();
|
||||
}
|
||||
|
||||
class _ATextFormFieldState extends State<ATextFormField> {
|
||||
@override
|
||||
void initState() {
|
||||
if (widget.controller != null) widget.controller.text = widget.initialValue;
|
||||
super.initState();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Container(
|
||||
height: widget.textInputType == TextInputType.multiline ? null : 50,
|
||||
padding: EdgeInsets.only(left: 12, right: 12),
|
||||
decoration: BoxDecoration(
|
||||
color: Color(0xfff5f5f5),
|
||||
border: Border.all(
|
||||
color: Color(0xffefefef),
|
||||
),
|
||||
borderRadius: BorderRadius.circular(AppStyle.borderRadius * AppStyle.getScaleFactor(context)),
|
||||
),
|
||||
child: TextFormField(
|
||||
focusNode: widget.node,
|
||||
enabled: widget.enable,
|
||||
onSaved: widget.onSaved,
|
||||
initialValue: widget.controller != null ? null : widget.initialValue,
|
||||
validator: widget.validator,
|
||||
onChanged: widget.onChange,
|
||||
textAlign: TextAlign.left,
|
||||
obscureText: widget.obscureText ?? false,
|
||||
keyboardType: widget.textInputType,
|
||||
maxLines: widget.textInputType == TextInputType.multiline ? null : 1,
|
||||
obscuringCharacter: "●",
|
||||
controller: widget.controller,
|
||||
textInputAction: widget.textInputType == TextInputType.multiline ? null : widget.textInputAction ?? TextInputAction.next,
|
||||
onEditingComplete: widget.onAction ?? () => FocusScope.of(context).nextFocus(),
|
||||
// style: widget.style,
|
||||
style: Theme.of(context).textTheme.bodyText1,
|
||||
decoration: InputDecoration(
|
||||
border: InputBorder.none,
|
||||
suffixIconConstraints: BoxConstraints(minWidth: 0),
|
||||
disabledBorder: InputBorder.none,
|
||||
focusedBorder: InputBorder.none,
|
||||
enabledBorder: InputBorder.none,
|
||||
constraints: BoxConstraints(),
|
||||
errorStyle: TextStyle(height: 0.3),
|
||||
//contentPadding: EdgeInsets.only(left: 0),
|
||||
hintText: widget.hintText,
|
||||
labelText: widget.labelText,
|
||||
//suffixIcon: widget.suffixIcon,
|
||||
suffixIcon: widget.prefixIconData == null
|
||||
? null
|
||||
: Icon(widget.prefixIconData,
|
||||
size: widget.prefixIconSize == null ? 20 * AppStyle.getScaleFactor(context) : (widget.prefixIconSize - 10) * AppStyle.getScaleFactor(context), color: Color(0xff2e303a))),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -1,61 +0,0 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:test_sa/controllers/localization/localization.dart';
|
||||
import 'package:test_sa/models/device/device_transfer_info.dart';
|
||||
import 'package:test_sa/views/app_style/colors.dart';
|
||||
import 'package:test_sa/views/widgets/loaders/image_loader.dart';
|
||||
import 'package:test_sa/views/widgets/requests/info_row.dart';
|
||||
import 'package:test_sa/views/widgets/requests/request_status.dart';
|
||||
class DeviceTransferInfoSection extends StatelessWidget {
|
||||
final DeviceTransferInfo info;
|
||||
final VoidCallback onEdit;
|
||||
const DeviceTransferInfoSection({Key key, this.info, this.onEdit}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final subtitle = AppLocalization.of(context).subtitle;
|
||||
return Column(
|
||||
children: [
|
||||
RequestInfoRow(
|
||||
title: subtitle.hospital,
|
||||
info: info.client.name,
|
||||
),
|
||||
RequestInfoRow(
|
||||
title: subtitle.unite,
|
||||
info: info.department.name,
|
||||
),
|
||||
RequestInfoRow(
|
||||
title: subtitle.engineerName,
|
||||
info: info.name,
|
||||
),
|
||||
RequestInfoRow(
|
||||
title: subtitle.workingHours,
|
||||
info: info.workingHours,
|
||||
),
|
||||
RequestInfoRow(
|
||||
title: subtitle.travelingHours,
|
||||
info: info.travelingHours,
|
||||
),
|
||||
RequestInfoRow(
|
||||
title: "Comment",
|
||||
info: info.comment,
|
||||
),
|
||||
RequestInfoRow(
|
||||
title: "Signature",
|
||||
info: info.signature?.isEmpty != false
|
||||
? subtitle.noDateFound : null,
|
||||
contentWidget: info.signature?.isEmpty != false ? null :
|
||||
ImageLoader(
|
||||
url: info.signature,
|
||||
),
|
||||
),
|
||||
RequestInfoRow(
|
||||
title: subtitle.status,
|
||||
infoWidget: StatusLabel(
|
||||
label: info.status?.label,
|
||||
color: AColors.getGasStatusColor(info.status?.id)
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -1,46 +0,0 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:test_sa/controllers/localization/localization.dart';
|
||||
import 'package:test_sa/models/device/device_transfer.dart';
|
||||
import 'package:test_sa/models/subtitle.dart';
|
||||
import 'package:test_sa/views/pages/device_transfer/device_transfer_details.dart';
|
||||
import 'package:test_sa/views/widgets/device_trancfer/device_transfer_item.dart';
|
||||
import 'package:test_sa/views/widgets/loaders/lazy_loading.dart';
|
||||
import 'package:test_sa/views/widgets/loaders/no_item_found.dart';
|
||||
class DeviceTransferList extends StatelessWidget {
|
||||
final List<DeviceTransfer> items;
|
||||
final bool nextPage;
|
||||
final Future<void> Function() onLazyLoad;
|
||||
|
||||
const DeviceTransferList({Key key, this.items, this.nextPage, this.onLazyLoad}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
|
||||
if(items.length == 0){
|
||||
Subtitle subtitle = AppLocalization.of(context).subtitle;
|
||||
return NoItemFound(message: subtitle.noServiceRequestFound,);
|
||||
}
|
||||
return LazyLoading(
|
||||
nextPage: nextPage,
|
||||
onLazyLoad: onLazyLoad,
|
||||
child: ListView.builder(
|
||||
//physics: const BouncingScrollPhysics(),
|
||||
itemCount: items.length,
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16,vertical: 8),
|
||||
itemBuilder: (context,itemIndex){
|
||||
return DeviceTransferItem(
|
||||
index: itemIndex,
|
||||
item: items[itemIndex],
|
||||
onPressed: (model){
|
||||
Navigator.of(context).push(
|
||||
MaterialPageRoute(
|
||||
builder: (_)=> DeviceTransferDetails(model: model,)
|
||||
)
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -1,63 +0,0 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:test_sa/controllers/localization/localization.dart';
|
||||
import 'package:test_sa/controllers/validator/validator.dart';
|
||||
import 'package:test_sa/models/gas_refill/gas_refill_details.dart';
|
||||
import 'package:test_sa/models/subtitle.dart';
|
||||
import 'package:test_sa/views/widgets/app_text_form_field.dart';
|
||||
import 'package:test_sa/views/widgets/requests/info_row.dart';
|
||||
import 'package:test_sa/views/widgets/titles/app_sub_title.dart';
|
||||
import 'package:test_sa/views/widgets/titles/app_title.dart';
|
||||
class GasRefillUpdateDetailsItem extends StatelessWidget {
|
||||
|
||||
final GasRefillDetails details;
|
||||
final bool enableEdit;
|
||||
final bool validate;
|
||||
|
||||
const GasRefillUpdateDetailsItem({Key key, this.details, this.enableEdit, this.validate}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
Subtitle subtitle = AppLocalization.of(context).subtitle;
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
ATitle(details.type.label),
|
||||
RequestInfoRow(
|
||||
title: "Cylinder Size",
|
||||
info: details.cylinderSize.label,
|
||||
),
|
||||
RequestInfoRow(
|
||||
title: "Requested Quantity",
|
||||
info: details.requestedQuantity.toStringAsFixed(0),
|
||||
),
|
||||
enableEdit ?
|
||||
Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
ASubTitle(subtitle.quantity),
|
||||
if(validate && details.deliveredQuantity == null)
|
||||
ASubTitle(subtitle.requiredWord,color: Colors.red,),
|
||||
SizedBox(height: 4,),
|
||||
ATextFormField(
|
||||
initialValue: (details.deliveredQuantity ?? "").toString(),
|
||||
textAlign: TextAlign.center,
|
||||
style: Theme.of(context).textTheme.subtitle1,
|
||||
validator: (value) =>
|
||||
Validator.isNumeric(value)
|
||||
? null : "allow numbers only",
|
||||
textInputType: TextInputType.number,
|
||||
onSaved: (value){
|
||||
details.deliveredQuantity = int.tryParse(value);
|
||||
},
|
||||
),
|
||||
],
|
||||
):
|
||||
RequestInfoRow(
|
||||
title: "Delivered Quantity",
|
||||
info: details.deliveredQuantity.toStringAsFixed(0),
|
||||
),
|
||||
//SizedBox(height: 16,)
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -1,74 +0,0 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:test_sa/views/app_style/sizing.dart';
|
||||
class RequestInfoRow extends StatelessWidget {
|
||||
final String title;
|
||||
final String info;
|
||||
final String content;
|
||||
final Widget contentWidget;
|
||||
final Widget infoWidget;
|
||||
|
||||
const RequestInfoRow({Key key, this.title, this.info,this.content, this.contentWidget, this.infoWidget}) : super(key: key);
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
if(info != null && info.isEmpty){
|
||||
return SizedBox.shrink();
|
||||
}
|
||||
if(content != null && content.isEmpty){
|
||||
return SizedBox.shrink();
|
||||
}
|
||||
return Column(
|
||||
children: [
|
||||
Row(
|
||||
children: [
|
||||
Text(
|
||||
title + " : ",
|
||||
style: Theme.of(context).textTheme.subtitle2.copyWith(
|
||||
//fontSize: 12
|
||||
),
|
||||
textScaleFactor: AppStyle.getScaleFactor(context),
|
||||
),
|
||||
|
||||
if(info != null)
|
||||
Expanded(
|
||||
child: Text(
|
||||
info,
|
||||
style: Theme.of(context).textTheme.bodyText2,
|
||||
textAlign: TextAlign.right,
|
||||
textScaleFactor: AppStyle.getScaleFactor(context),
|
||||
),
|
||||
),
|
||||
if(infoWidget != null)
|
||||
Expanded(
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.end,
|
||||
children: [
|
||||
infoWidget,
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
|
||||
if(content != null)
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 8),
|
||||
child: Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: Text(
|
||||
content ?? 'No data found',
|
||||
style: Theme.of(context).textTheme.bodyText2,
|
||||
textAlign: TextAlign.center,
|
||||
textScaleFactor: AppStyle.getScaleFactor(context),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
if(contentWidget != null)
|
||||
contentWidget,
|
||||
Divider(color: Theme.of(context).primaryColor,),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -1,35 +0,0 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:test_sa/views/app_style/colors.dart';
|
||||
import 'package:test_sa/views/app_style/sizing.dart';
|
||||
class StatusLabel extends StatelessWidget {
|
||||
final String label;
|
||||
final Color color;
|
||||
|
||||
const StatusLabel({Key key, this.label, this.color}) : super(key: key);
|
||||
|
||||
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Container(
|
||||
padding: EdgeInsets.symmetric(vertical: 2,horizontal: 8),
|
||||
alignment: Alignment.center,
|
||||
decoration: BoxDecoration(
|
||||
color: color ?? Colors.green,
|
||||
borderRadius: BorderRadius.circular(
|
||||
AppStyle.getBorderRadius(context)
|
||||
),
|
||||
boxShadow: [
|
||||
AppStyle.boxShadow
|
||||
]
|
||||
),
|
||||
child: Text(
|
||||
label ?? "no status",
|
||||
style: Theme.of(context).textTheme.subtitle2.copyWith(
|
||||
color: color.computeLuminance() > 0.5
|
||||
? AColors.black : Colors.white,
|
||||
),
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -1,266 +0,0 @@
|
||||
import 'package:fluttertoast/fluttertoast.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/user_provider.dart';
|
||||
import 'package:test_sa/controllers/providers/settings/setting_provider.dart';
|
||||
import 'package:test_sa/models/enums/user_types.dart';
|
||||
import 'package:test_sa/models/service_request/service_request.dart';
|
||||
import 'package:test_sa/models/subtitle.dart';
|
||||
import 'package:test_sa/models/user.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/user/requests/report/create_service_report.dart';
|
||||
import 'package:test_sa/views/pages/user/requests/report/future_service_report.dart';
|
||||
import 'package:test_sa/views/widgets/loaders/image_loader.dart';
|
||||
import 'package:test_sa/views/widgets/requests/request_status.dart';
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:intl/intl.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:test_sa/views/widgets/timer/app_timer.dart';
|
||||
|
||||
import '../../../controllers/http_status_manger/http_status_manger.dart';
|
||||
class ServiceRequestItem extends StatelessWidget {
|
||||
final int index;
|
||||
final ServiceRequest request;
|
||||
final Function(ServiceRequest) onPressed;
|
||||
const ServiceRequestItem({Key key, this.request, this.onPressed, this.index}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
Subtitle _subtitle = AppLocalization.of(context).subtitle;
|
||||
User _user = Provider.of<UserProvider>(context,listen: false).user;
|
||||
final servicesProvider = Provider.of<ServiceRequestsProvider>(context,listen: false);
|
||||
final settingProvider = Provider.of<SettingProvider>(context,listen: false);
|
||||
Color itemColor = index % 2 == 0
|
||||
? Theme.of(context).colorScheme.primary
|
||||
: Theme.of(context).colorScheme.onPrimary;
|
||||
Color onItemColor = index % 2 != 0
|
||||
? Theme.of(context).colorScheme.primary
|
||||
: Theme.of(context).colorScheme.onPrimary;
|
||||
|
||||
return Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 4),
|
||||
child: ElevatedButton(
|
||||
style: ElevatedButton.styleFrom(
|
||||
padding: EdgeInsets.symmetric(vertical: 8,horizontal: 8),
|
||||
primary: itemColor,
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(
|
||||
AppStyle.getBorderRadius(context)
|
||||
),
|
||||
),
|
||||
),
|
||||
//padding: EdgeInsets.symmetric(vertical: 8,horizontal: 8),
|
||||
onPressed: (){
|
||||
onPressed(request);
|
||||
},
|
||||
child: Row(
|
||||
children: [
|
||||
//Placeholder(color: onItemColor,fallbackWidth: 80,fallbackHeight: 80,),
|
||||
_user.type == UsersTypes.normal_user && request.devicePhotos.isEmpty ? SizedBox.shrink():
|
||||
SizedBox(
|
||||
width: 80,
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
request.devicePhotos.isEmpty ? SizedBox.shrink():
|
||||
Column(
|
||||
children: [
|
||||
SizedBox(
|
||||
height: 80,
|
||||
width: 80,
|
||||
child: ImageLoader(
|
||||
url: request.devicePhotos.first,
|
||||
boxFit: BoxFit.cover,
|
||||
),
|
||||
),
|
||||
SizedBox(height: 24,),
|
||||
],
|
||||
),
|
||||
|
||||
_user.type == UsersTypes.engineer ?
|
||||
Material(
|
||||
color: onItemColor,
|
||||
elevation: 6,
|
||||
shape: CircleBorder(),
|
||||
child: IconButton(
|
||||
icon: Icon(
|
||||
Icons.description,
|
||||
color: itemColor,
|
||||
size: 32,
|
||||
),
|
||||
onPressed: (){
|
||||
Navigator.of(context).push(
|
||||
MaterialPageRoute(
|
||||
builder: (_) => CreateServiceReport(
|
||||
request: request,
|
||||
)
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
) :SizedBox.shrink(),
|
||||
//SizedBox(height: 8,),
|
||||
|
||||
],
|
||||
),
|
||||
),
|
||||
SizedBox(width: 8,),
|
||||
Expanded(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: request.requestCode == null ? SizedBox.shrink():
|
||||
Text(
|
||||
request.requestCode ?? "-----",
|
||||
style: Theme.of(context).textTheme.headline6.copyWith(
|
||||
color: onItemColor,
|
||||
fontSize: 16,
|
||||
fontWeight: FontWeight.bold
|
||||
),
|
||||
),
|
||||
),
|
||||
request.engineerName == null ? SizedBox.shrink():
|
||||
Text(
|
||||
request.engineerName ?? "",
|
||||
style: Theme.of(context).textTheme.subtitle2.copyWith(
|
||||
color: onItemColor,
|
||||
fontSize: 12,
|
||||
fontWeight: FontWeight.normal
|
||||
),
|
||||
),
|
||||
|
||||
],
|
||||
),
|
||||
Divider(color: onItemColor,),
|
||||
Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: request.deviceModel == null ? SizedBox.shrink():
|
||||
Text(
|
||||
request.deviceModel ?? "Model not available",
|
||||
style: Theme.of(context).textTheme.subtitle2.copyWith(
|
||||
color: onItemColor,
|
||||
fontSize: 12,
|
||||
fontWeight: FontWeight.normal
|
||||
),
|
||||
),
|
||||
),
|
||||
request.engineerMobile == null ? SizedBox.shrink():
|
||||
Text(
|
||||
request.engineerMobile,
|
||||
style: Theme.of(context).textTheme.subtitle1.copyWith(
|
||||
color: onItemColor,
|
||||
fontSize: 12,
|
||||
fontWeight: FontWeight.normal
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
Divider(color: onItemColor,),
|
||||
Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: request.deviceSerialNumber == null ? SizedBox.shrink():
|
||||
Text(
|
||||
request.deviceSerialNumber,
|
||||
style: Theme.of(context).textTheme.subtitle2.copyWith(
|
||||
color: onItemColor,
|
||||
fontSize: 12,
|
||||
fontWeight: FontWeight.normal
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
request.deviceEnName == null ? SizedBox.shrink():
|
||||
Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: Text(
|
||||
request.deviceEnName,
|
||||
style: Theme.of(context).textTheme.subtitle1.copyWith(
|
||||
color: onItemColor,
|
||||
fontSize: 12,
|
||||
fontWeight: FontWeight.normal
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
||||
],
|
||||
),
|
||||
|
||||
Divider(color: onItemColor,),
|
||||
Center(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 8),
|
||||
child: Text(
|
||||
request.maintenanceIssue ?? "No maintenance issue found",
|
||||
style: Theme.of(context).textTheme.subtitle1.copyWith(
|
||||
color: onItemColor
|
||||
),
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
),
|
||||
),
|
||||
Divider(color: onItemColor,),
|
||||
Row(
|
||||
children: [
|
||||
Text(
|
||||
request.date ?? "Date not available",
|
||||
style: Theme.of(context).textTheme.subtitle2.copyWith(
|
||||
color: onItemColor
|
||||
),
|
||||
),
|
||||
Spacer(),
|
||||
StatusLabel(label: request.statusLabel,
|
||||
color: AColors.getRequestStatusColor(request.statusValue)),
|
||||
],
|
||||
),
|
||||
request.nextVisitDate == null ? SizedBox.shrink() :
|
||||
Column(
|
||||
children: [
|
||||
Divider(color: onItemColor,),
|
||||
Row(
|
||||
children: [
|
||||
Text(
|
||||
_subtitle.nextVisitDate,
|
||||
style: Theme.of(context).textTheme.subtitle2.copyWith(
|
||||
color: onItemColor
|
||||
),
|
||||
),
|
||||
Spacer(),
|
||||
Text(
|
||||
DateFormat('EE dd/MM/yyyy').format(request.nextVisitDate),
|
||||
style: Theme.of(context).textTheme.subtitle2.copyWith(
|
||||
color: onItemColor
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -1,46 +0,0 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:test_sa/controllers/localization/localization.dart';
|
||||
import 'package:test_sa/models/service_request/service_request.dart';
|
||||
import 'package:test_sa/models/subtitle.dart';
|
||||
import 'package:test_sa/views/pages/user/requests/request_details.dart';
|
||||
import 'package:test_sa/views/widgets/loaders/lazy_loading.dart';
|
||||
import 'package:test_sa/views/widgets/loaders/no_item_found.dart';
|
||||
import 'package:test_sa/views/widgets/requests/service_request_item.dart';
|
||||
class ServiceRequestsList extends StatelessWidget {
|
||||
final List<ServiceRequest> requests;
|
||||
final bool nextPage;
|
||||
final Future<void> Function() onLazyLoad;
|
||||
|
||||
const ServiceRequestsList({Key key, this.requests, this.nextPage, this.onLazyLoad}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
|
||||
Subtitle _subtitle = AppLocalization.of(context).subtitle;
|
||||
if(requests.length == 0){
|
||||
return NoItemFound(message: _subtitle.noServiceRequestFound,);
|
||||
}
|
||||
return LazyLoading(
|
||||
nextPage: nextPage,
|
||||
onLazyLoad: onLazyLoad,
|
||||
child: ListView.builder(
|
||||
//physics: BouncingScrollPhysics(),
|
||||
itemCount: requests.length,
|
||||
padding: EdgeInsets.symmetric(horizontal: 16,vertical: 8),
|
||||
itemBuilder: (context,itemIndex){
|
||||
return ServiceRequestItem(
|
||||
index: itemIndex,
|
||||
request: requests[itemIndex],
|
||||
onPressed: (request){
|
||||
Navigator.of(context).push(
|
||||
MaterialPageRoute(
|
||||
builder: (_)=> RequestDetailsPage(serviceRequest: request,)
|
||||
)
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -1,149 +0,0 @@
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:fluttertoast/fluttertoast.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:test_sa/controllers/http_status_manger/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/user_provider.dart';
|
||||
import 'package:test_sa/controllers/providers/settings/setting_provider.dart';
|
||||
import 'package:test_sa/models/service_request/service_request.dart';
|
||||
import 'package:test_sa/models/service_request/service_request_search.dart';
|
||||
import 'package:test_sa/models/lookup.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/buttons/app_small_button.dart';
|
||||
import 'package:test_sa/views/widgets/date_and_time/date_picker.dart';
|
||||
import 'package:test_sa/views/widgets/hospitals/hospital_auto_complete_field.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:test_sa/views/widgets/status/employee/employee_mune.dart';
|
||||
|
||||
import '../app_text_form_field.dart';
|
||||
|
||||
class ServiceRequestsUpdateDialog extends StatefulWidget {
|
||||
final ServiceRequest request;
|
||||
const ServiceRequestsUpdateDialog({
|
||||
Key key, this.request,
|
||||
}) : super(key: key);
|
||||
@override
|
||||
State<ServiceRequestsUpdateDialog> createState() => _ServiceRequestsUpdateDialogState();
|
||||
}
|
||||
|
||||
class _ServiceRequestsUpdateDialogState extends State<ServiceRequestsUpdateDialog>
|
||||
with TickerProviderStateMixin{
|
||||
|
||||
DateTime _dateTime;
|
||||
Lookup _employee;
|
||||
Subtitle _subtitle;
|
||||
UserProvider _userProvider;
|
||||
SettingProvider _settingProvider;
|
||||
ServiceRequestsProvider _serviceRequestsProvider;
|
||||
|
||||
final GlobalKey<FormState> _formKey = GlobalKey<FormState>();
|
||||
|
||||
_update() async {
|
||||
if(_dateTime == null && _employee == null){
|
||||
Fluttertoast.showToast(
|
||||
msg: _subtitle.noDateFound,
|
||||
);
|
||||
return;
|
||||
}
|
||||
showDialog<void>(
|
||||
context: context,
|
||||
barrierDismissible: false,
|
||||
builder: (BuildContext context) {
|
||||
return CupertinoAlertDialog(
|
||||
title: Text(_subtitle.updatingDots),
|
||||
content: Center(child: CircularProgressIndicator()),
|
||||
);
|
||||
},
|
||||
);
|
||||
int status = await _serviceRequestsProvider.updateDate(
|
||||
user: _userProvider.user,
|
||||
host: _settingProvider.host,
|
||||
request: widget.request,
|
||||
newDate: _dateTime?.toString()?.split(" ")?.first,
|
||||
employee: _employee
|
||||
);
|
||||
if(status == 200) Navigator.of(context).pop();
|
||||
Navigator.of(context).pop();
|
||||
Fluttertoast.showToast(
|
||||
msg: HttpStatusManger.getStatusMessage(status: status, subtitle: _subtitle),
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
_subtitle = AppLocalization.of(context).subtitle;
|
||||
_userProvider = Provider.of<UserProvider>(context,listen: false);
|
||||
_settingProvider = Provider.of<SettingProvider>(context,listen: false);
|
||||
_serviceRequestsProvider = Provider.of<ServiceRequestsProvider>(context,listen: false);
|
||||
return Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
SizedBox(
|
||||
// height: MediaQuery.of(context).size.height / 1.2,
|
||||
child: Form(
|
||||
key: _formKey,
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(16.0),
|
||||
child: Column(
|
||||
children: [
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
ASmallButton(
|
||||
text: _subtitle.cancel,
|
||||
onPressed: (){
|
||||
Navigator.of(context).pop();
|
||||
},
|
||||
),
|
||||
|
||||
ASmallButton(
|
||||
text: _subtitle.update,
|
||||
onPressed: _update,
|
||||
)
|
||||
],
|
||||
),
|
||||
SizedBox(height: 8.0 * AppStyle.getScaleFactor(context),),
|
||||
Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: Text(
|
||||
_subtitle.date,
|
||||
style: Theme.of(context).textTheme.subtitle1,
|
||||
textScaleFactor: AppStyle.getScaleFactor(context),
|
||||
),
|
||||
),
|
||||
ADatePicker(
|
||||
date: _dateTime,
|
||||
from: DateTime.now(),
|
||||
onDatePicker: (date){
|
||||
_dateTime = date;
|
||||
setState(() {});
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
SizedBox(height: 8.0 * AppStyle.getScaleFactor(context),),
|
||||
EmployeeMenu(
|
||||
initialValue: _employee,
|
||||
onSelect: (employee){
|
||||
_employee = employee;
|
||||
},
|
||||
),
|
||||
SizedBox(height: 8.0 * AppStyle.getScaleFactor(context),),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -1,59 +0,0 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:test_sa/models/lookup.dart';
|
||||
import 'package:test_sa/views/app_style/colors.dart';
|
||||
import 'package:test_sa/views/app_style/sizing.dart';
|
||||
|
||||
class FilterItem extends StatelessWidget {
|
||||
final bool isSelected;
|
||||
final Lookup status;
|
||||
final VoidCallback onSelected;
|
||||
|
||||
const FilterItem({
|
||||
Key key,
|
||||
this.status,
|
||||
this.isSelected,
|
||||
this.onSelected
|
||||
}) : super(key: key);
|
||||
|
||||
Color getStatusColor(){
|
||||
switch(status.id){
|
||||
case 0: return AColors.green;
|
||||
case 4: return AColors.deepRed;
|
||||
case 6: return AColors.green;
|
||||
case 5: return AColors.orange;
|
||||
case 8: return AColors.green;
|
||||
case 9: return AColors.orange;
|
||||
default : return AColors.grey;
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Opacity(
|
||||
opacity: isSelected ? 1 : .5,
|
||||
child: SizedBox(
|
||||
height: 30,
|
||||
child: ElevatedButton(
|
||||
style: ElevatedButton.styleFrom(
|
||||
padding: EdgeInsets.symmetric(horizontal: 8),
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(
|
||||
AppStyle.getBorderRadius(context)
|
||||
)
|
||||
),
|
||||
primary: getStatusColor(),
|
||||
),
|
||||
child: Text(
|
||||
status.label??"",
|
||||
style: Theme.of(context).textTheme.bodyText1.copyWith(
|
||||
color:getStatusColor().computeLuminance() > 0.5
|
||||
? AColors.black : Colors.white,
|
||||
),
|
||||
textScaleFactor: AppStyle.getScaleFactor(context),
|
||||
),
|
||||
onPressed:onSelected,
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -1,188 +0,0 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:test_sa/controllers/localization/localization.dart';
|
||||
import 'package:test_sa/models/lookup.dart';
|
||||
import 'package:test_sa/models/service_request/service_request_search.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/buttons/app_small_button.dart';
|
||||
import 'package:test_sa/views/widgets/hospitals/hospital_auto_complete_field.dart';
|
||||
|
||||
import '../app_text_form_field.dart';
|
||||
import 'filter_item.dart';
|
||||
class ServiceRequestsSearchDialog extends StatefulWidget {
|
||||
final ServiceRequestSearch initialSearchValue;
|
||||
final bool expandedSearch;
|
||||
final Function(ServiceRequestSearch) onSearch;
|
||||
|
||||
const ServiceRequestsSearchDialog({
|
||||
Key key,
|
||||
this.initialSearchValue,
|
||||
this.expandedSearch,
|
||||
this.onSearch
|
||||
}) : super(key: key);
|
||||
@override
|
||||
_ServiceRequestsSearchDialogState createState() => _ServiceRequestsSearchDialogState();
|
||||
}
|
||||
|
||||
class _ServiceRequestsSearchDialogState extends State<ServiceRequestsSearchDialog>
|
||||
with TickerProviderStateMixin{
|
||||
ServiceRequestSearch _search;
|
||||
List<Lookup> status = [
|
||||
Lookup(label: "New", id: 4,),
|
||||
|
||||
Lookup(label: "Repaired", id: 6,),
|
||||
Lookup(label: "Repeated", id: 8),
|
||||
Lookup(label: "Closed", id: 9,),
|
||||
Lookup(label: "Under Repair", id: 5,),
|
||||
];
|
||||
|
||||
final GlobalKey<FormState> _formKey = GlobalKey<FormState>();
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_search = ServiceRequestSearch();
|
||||
_search.fromSearch(widget.initialSearchValue);
|
||||
}
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
Subtitle _subtitle = AppLocalization.of(context).subtitle;
|
||||
return SizedBox(
|
||||
height: MediaQuery.of(context).size.height / 1.2,
|
||||
child: Form(
|
||||
key: _formKey,
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(16.0),
|
||||
child: Column(
|
||||
children: [
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
ASmallButton(
|
||||
text: _subtitle.cancel,
|
||||
onPressed: (){
|
||||
Navigator.of(context).pop();
|
||||
},
|
||||
),
|
||||
|
||||
ASmallButton(
|
||||
text: _subtitle.search,
|
||||
onPressed: (){
|
||||
if(!_formKey.currentState.validate())
|
||||
return;
|
||||
_formKey.currentState.save();
|
||||
Navigator.of(context).pop(_search);
|
||||
},
|
||||
)
|
||||
],
|
||||
),
|
||||
SizedBox(height: 8.0 * AppStyle.getScaleFactor(context),),
|
||||
ATextFormField(
|
||||
initialValue: _search.deviceSerialNumber,
|
||||
hintText: _subtitle.serialNumber,
|
||||
style: Theme.of(context).textTheme.headline6,
|
||||
textInputAction: TextInputAction.search,
|
||||
onAction: (){
|
||||
if(!_formKey.currentState.validate())
|
||||
return;
|
||||
_formKey.currentState.save();
|
||||
Navigator.of(context).pop(_search);
|
||||
},
|
||||
onSaved: (value){
|
||||
_search.deviceSerialNumber = value;
|
||||
},
|
||||
),
|
||||
SizedBox(height: 8.0 * AppStyle.getScaleFactor(context),),
|
||||
HospitalAutoCompleteField(
|
||||
initialValue: _search.hospital,
|
||||
onSave: (value){
|
||||
_search.hospital = value;
|
||||
},
|
||||
onSearch: (value){
|
||||
_search.hospital = value;
|
||||
Navigator.of(context).pop(_search);
|
||||
},
|
||||
),
|
||||
SizedBox(height: 8.0 * AppStyle.getScaleFactor(context),),
|
||||
ATextFormField(
|
||||
initialValue: _search.deviceName,
|
||||
hintText: _subtitle.deviceName,
|
||||
style: Theme.of(context).textTheme.headline6,
|
||||
textInputAction: TextInputAction.search,
|
||||
onAction: (){
|
||||
if(!_formKey.currentState.validate())
|
||||
return;
|
||||
_formKey.currentState.save();
|
||||
Navigator.of(context).pop(_search);
|
||||
},
|
||||
onSaved: (value){
|
||||
_search.deviceName = value;
|
||||
},
|
||||
),
|
||||
SizedBox(height: 8.0 * AppStyle.getScaleFactor(context),),
|
||||
ATextFormField(
|
||||
initialValue: _search.model,
|
||||
hintText: _subtitle.model,
|
||||
style: Theme.of(context).textTheme.headline6,
|
||||
textInputAction: TextInputAction.search,
|
||||
onAction: (){
|
||||
if(!_formKey.currentState.validate())
|
||||
return;
|
||||
_formKey.currentState.save();
|
||||
Navigator.of(context).pop(_search);
|
||||
},
|
||||
onSaved: (value){
|
||||
_search.model = value;
|
||||
},
|
||||
),
|
||||
SizedBox(height: 16 * AppStyle.getScaleFactor(context),),
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 12),
|
||||
child: Wrap(
|
||||
spacing: 10,
|
||||
runSpacing: 10,
|
||||
alignment: WrapAlignment.spaceEvenly,
|
||||
children: List.generate(
|
||||
status.length,
|
||||
(index) {
|
||||
bool isSelected = _search.statusValue == status[index].id;
|
||||
return FilterItem(
|
||||
isSelected: isSelected,
|
||||
onSelected: (){
|
||||
if(isSelected)
|
||||
_search.statusValue = null;
|
||||
else
|
||||
_search.statusValue = status[index].id;
|
||||
|
||||
setState(() {});
|
||||
},
|
||||
status: status[index],
|
||||
);
|
||||
}
|
||||
|
||||
),
|
||||
),
|
||||
),
|
||||
|
||||
Visibility(
|
||||
visible: widget.initialSearchValue.toSearchString().isNotEmpty,
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 8,horizontal: 16),
|
||||
child: AButton(
|
||||
padding: EdgeInsets.zero,
|
||||
text: _subtitle.clearSearch,
|
||||
onPressed: (){
|
||||
_search = ServiceRequestSearch();
|
||||
Navigator.of(context).pop(_search);
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -1,242 +0,0 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:test_sa/controllers/localization/localization.dart';
|
||||
import 'package:test_sa/models/lookup.dart';
|
||||
import 'package:test_sa/models/subtitle.dart';
|
||||
import 'package:test_sa/models/visits/visits_search.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/buttons/app_small_button.dart';
|
||||
import 'package:test_sa/views/widgets/date_and_time/from_to_date_bar.dart';
|
||||
import 'package:test_sa/views/widgets/hospitals/hospital_auto_complete_field.dart';
|
||||
import 'package:test_sa/views/widgets/titles/app_sub_title.dart';
|
||||
|
||||
import '../app_text_form_field.dart';
|
||||
import 'filter_item.dart';
|
||||
class VisitsSearchDialog extends StatefulWidget {
|
||||
final VisitsSearch initialSearchValue;
|
||||
final bool expandedSearch;
|
||||
final Function(VisitsSearch) onSearch;
|
||||
|
||||
const VisitsSearchDialog({
|
||||
Key key,
|
||||
this.initialSearchValue,
|
||||
this.expandedSearch,
|
||||
this.onSearch
|
||||
}) : super(key: key);
|
||||
@override
|
||||
_VisitsSearchDialogState createState() => _VisitsSearchDialogState();
|
||||
}
|
||||
|
||||
class _VisitsSearchDialogState extends State<VisitsSearchDialog>
|
||||
with TickerProviderStateMixin{
|
||||
VisitsSearch _search;
|
||||
List<Lookup> status = [
|
||||
Lookup(label: "Done", id: 0,),
|
||||
Lookup(label: "Not Yet", id: 1),
|
||||
Lookup(label: "On Hold", id: 2,),
|
||||
];
|
||||
|
||||
List<Lookup> contactStatus = [
|
||||
Lookup(label: "Hospital Employee", key: "H",),
|
||||
Lookup(label: "Under Warranty", key: "CW"),
|
||||
Lookup(label: "Under Maintenance Contract", key: "CC",),
|
||||
];
|
||||
|
||||
|
||||
final GlobalKey<FormState> _formKey = GlobalKey<FormState>();
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_search = VisitsSearch();
|
||||
_search.fromSearch(widget.initialSearchValue);
|
||||
}
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
Subtitle _subtitle = AppLocalization.of(context).subtitle;
|
||||
DateTime today = DateTime.now();
|
||||
return SizedBox(
|
||||
height: MediaQuery.of(context).size.height / 1.3,
|
||||
child: Form(
|
||||
key: _formKey,
|
||||
child: ListView(
|
||||
padding: const EdgeInsets.symmetric(vertical: 8,horizontal: 16),
|
||||
children: [
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
ASmallButton(
|
||||
text: _subtitle.cancel,
|
||||
onPressed: (){
|
||||
Navigator.of(context).pop();
|
||||
},
|
||||
),
|
||||
|
||||
ASmallButton(
|
||||
text: _subtitle.search,
|
||||
onPressed: (){
|
||||
if(!_formKey.currentState.validate())
|
||||
return;
|
||||
_formKey.currentState.save();
|
||||
Navigator.of(context).pop(_search);
|
||||
},
|
||||
)
|
||||
],
|
||||
),
|
||||
ATextFormField(
|
||||
initialValue: _search.deviceSerialNumber,
|
||||
hintText: _subtitle.serialNumber,
|
||||
style: Theme.of(context).textTheme.headline6,
|
||||
textInputAction: TextInputAction.search,
|
||||
onAction: (){
|
||||
if(!_formKey.currentState.validate())
|
||||
return;
|
||||
_formKey.currentState.save();
|
||||
Navigator.of(context).pop(_search);
|
||||
},
|
||||
onSaved: (value){
|
||||
_search.deviceSerialNumber = value;
|
||||
},
|
||||
),
|
||||
SizedBox(height: 8.0 * AppStyle.getScaleFactor(context),),
|
||||
HospitalAutoCompleteField(
|
||||
initialValue: _search.hospitalName,
|
||||
onSave: (value){
|
||||
_search.hospitalName = value;
|
||||
},
|
||||
onSearch: (value){
|
||||
_search.hospitalName = value;
|
||||
Navigator.of(context).pop(_search);
|
||||
},
|
||||
),
|
||||
SizedBox(height: 8.0 * AppStyle.getScaleFactor(context),),
|
||||
ATextFormField(
|
||||
initialValue: _search.brand,
|
||||
hintText: _subtitle.brand,
|
||||
style: Theme.of(context).textTheme.headline6,
|
||||
textInputAction: TextInputAction.search,
|
||||
onAction: (){
|
||||
if(!_formKey.currentState.validate())
|
||||
return;
|
||||
_formKey.currentState.save();
|
||||
Navigator.of(context).pop(_search);
|
||||
},
|
||||
onSaved: (value){
|
||||
_search.brand = value;
|
||||
},
|
||||
),
|
||||
SizedBox(height: 8.0 * AppStyle.getScaleFactor(context),),
|
||||
ATextFormField(
|
||||
initialValue: _search.model,
|
||||
hintText: _subtitle.model,
|
||||
style: Theme.of(context).textTheme.headline6,
|
||||
textInputAction: TextInputAction.search,
|
||||
onAction: (){
|
||||
if(!_formKey.currentState.validate())
|
||||
return;
|
||||
_formKey.currentState.save();
|
||||
Navigator.of(context).pop(_search);
|
||||
},
|
||||
onSaved: (value){
|
||||
_search.model = value;
|
||||
},
|
||||
),
|
||||
SizedBox(height: 8.0 * AppStyle.getScaleFactor(context),),
|
||||
ASubTitle(_subtitle.status),
|
||||
SizedBox(height: 4.0 * AppStyle.getScaleFactor(context),),
|
||||
Wrap(
|
||||
spacing: 10,
|
||||
runSpacing: 10,
|
||||
children: List.generate(
|
||||
status.length,
|
||||
(index) {
|
||||
bool isSelected = _search.statusValue == status[index].id;
|
||||
return FilterItem(
|
||||
isSelected: isSelected,
|
||||
onSelected: (){
|
||||
if(isSelected)
|
||||
_search.statusValue = null;
|
||||
else
|
||||
_search.statusValue = status[index].id;
|
||||
|
||||
setState(() {});
|
||||
},
|
||||
status: status[index],
|
||||
);
|
||||
}
|
||||
|
||||
),
|
||||
),
|
||||
SizedBox(height: 8.0 * AppStyle.getScaleFactor(context),),
|
||||
ASubTitle(_subtitle.contactStatus),
|
||||
SizedBox(height: 4.0 * AppStyle.getScaleFactor(context),),
|
||||
Wrap(
|
||||
spacing: 10,
|
||||
runSpacing: 10,
|
||||
children: List.generate(
|
||||
contactStatus.length,
|
||||
(index) {
|
||||
bool isSelected = _search.contactStatus == contactStatus[index].key;
|
||||
return FilterItem(
|
||||
isSelected: isSelected,
|
||||
onSelected: (){
|
||||
if(isSelected)
|
||||
_search.contactStatus = null;
|
||||
else
|
||||
_search.contactStatus = contactStatus[index].key;
|
||||
|
||||
setState(() {});
|
||||
},
|
||||
status: contactStatus[index],
|
||||
);
|
||||
}
|
||||
|
||||
),
|
||||
),
|
||||
SizedBox(height: 8.0 * AppStyle.getScaleFactor(context),),
|
||||
ASubTitle(_subtitle.actualDate),
|
||||
SizedBox(height: 4.0 * AppStyle.getScaleFactor(context),),
|
||||
FromToDateBar(
|
||||
from: _search.actualDateFrom ,
|
||||
to: _search.actualDateTo,
|
||||
onPickFrom: (date){
|
||||
_search.actualDateFrom = date;
|
||||
},
|
||||
onPickTo: (date){
|
||||
_search.actualDateTo = date;
|
||||
},
|
||||
),
|
||||
SizedBox(height: 8.0 * AppStyle.getScaleFactor(context),),
|
||||
ASubTitle(_subtitle.expectDate),
|
||||
SizedBox(height: 4.0 * AppStyle.getScaleFactor(context),),
|
||||
FromToDateBar(
|
||||
from: _search.expectedDateFrom ?? DateTime(today.year, today.month, 1),
|
||||
to: _search.expectedDateTo ?? DateTime(today.year, (today.month +1).clamp(1, 12) , today.month == 12 ? 31 : 0),
|
||||
onPickFrom: (date){
|
||||
_search.expectedDateFrom = date;
|
||||
},
|
||||
onPickTo: (date){
|
||||
_search.expectedDateTo = date;
|
||||
},
|
||||
),
|
||||
Visibility(
|
||||
visible: _search.toSearchString().isNotEmpty,
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 8,horizontal: 16),
|
||||
child: AButton(
|
||||
padding: EdgeInsets.zero,
|
||||
text: _subtitle.clearSearch,
|
||||
onPressed: (){
|
||||
_search = VisitsSearch();
|
||||
Navigator.of(context).pop(_search);
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -1,239 +0,0 @@
|
||||
import 'dart:typed_data';
|
||||
|
||||
import 'package:audioplayers/audioplayers.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:test_sa/views/app_style/sizing.dart';
|
||||
|
||||
import '../../app_style/colors.dart';
|
||||
|
||||
class ASoundPlayer extends StatefulWidget {
|
||||
|
||||
final String audio;
|
||||
|
||||
const ASoundPlayer({Key key, this.audio}) : super(key: key);
|
||||
|
||||
@override
|
||||
_ASoundPlayerState createState() => _ASoundPlayerState();
|
||||
}
|
||||
|
||||
class _ASoundPlayerState extends State<ASoundPlayer> {
|
||||
|
||||
//FlutterSoundPlayer _myPlayer = FlutterSoundPlayer();
|
||||
bool _sliderMoving = false;
|
||||
Duration _audioTime;
|
||||
Duration _audioPosition;
|
||||
String _audio;
|
||||
bool _isLocalFile = false;
|
||||
bool _failedToLoad = false;
|
||||
AudioPlayer _audioPlayer;
|
||||
|
||||
Widget _getAudioButton(){
|
||||
switch(_audioPlayer.state){
|
||||
case PlayerState.playing:
|
||||
return IconButton(
|
||||
icon: const Icon(Icons.pause_rounded),
|
||||
onPressed: () async {
|
||||
_failedToLoad = false;
|
||||
await _audioPlayer.pause();
|
||||
rebuild();
|
||||
}
|
||||
);
|
||||
case PlayerState.paused:
|
||||
return IconButton(
|
||||
icon: const Icon(Icons.play_arrow_rounded),
|
||||
onPressed: () async {
|
||||
_failedToLoad = false;
|
||||
await _audioPlayer.resume();
|
||||
rebuild();
|
||||
}
|
||||
);
|
||||
case PlayerState.completed:
|
||||
return IconButton(
|
||||
icon: const Icon(Icons.replay_rounded),
|
||||
onPressed: () async {
|
||||
_failedToLoad = false;
|
||||
await _audioPlayer.stop();
|
||||
await _audioPlayer.resume();
|
||||
rebuild();
|
||||
}
|
||||
);
|
||||
case PlayerState.stopped:
|
||||
return IconButton(
|
||||
icon: Icon( _isLocalFile
|
||||
? Icons.play_circle_fill_outlined
|
||||
: Icons.download_rounded
|
||||
|
||||
),
|
||||
onPressed: () async {
|
||||
_failedToLoad = false;
|
||||
try {
|
||||
await _audioPlayer.play(
|
||||
_isLocalFile?
|
||||
DeviceFileSource(_audio):UrlSource(_audio),
|
||||
);
|
||||
rebuild();
|
||||
} on Exception catch (e) {
|
||||
_failedToLoad = true;
|
||||
}
|
||||
}
|
||||
);
|
||||
default: return IconButton(
|
||||
icon: const Icon( Icons.replay_rounded),
|
||||
onPressed: () async {
|
||||
_failedToLoad = false;
|
||||
try {
|
||||
_audioPlayer.seek(const Duration(milliseconds: 0));
|
||||
_audioPlayer.stop();
|
||||
await _audioPlayer.play(
|
||||
_isLocalFile?
|
||||
DeviceFileSource(_audio):UrlSource(_audio),
|
||||
);
|
||||
rebuild();
|
||||
} on Exception catch (e) {
|
||||
_failedToLoad = true;
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
String format(Duration d) {
|
||||
if(d == null)
|
||||
return "00:00";
|
||||
return d.toString().substring(2, 7);
|
||||
}
|
||||
|
||||
rebuild(){
|
||||
if (!mounted) return;
|
||||
setState(() {});
|
||||
}
|
||||
|
||||
bool _isLocalUrl(String url) {
|
||||
if(url?.isEmpty != false) return false;
|
||||
return url.startsWith("/") ||
|
||||
url.startsWith("file://") ||
|
||||
url.substring(1).startsWith(':\\');
|
||||
}
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_audioPlayer = AudioPlayer();
|
||||
_audioPlayer.release();
|
||||
_audio = widget.audio;
|
||||
_isLocalFile = _isLocalUrl(_audio);
|
||||
_audioPlayer.setReleaseMode(ReleaseMode.stop);
|
||||
if(_isLocalFile){
|
||||
_audioPlayer.setSourceDeviceFile(_audio).then((value) {rebuild();});
|
||||
} else{
|
||||
_audioPlayer.setReleaseMode(ReleaseMode.stop);
|
||||
}
|
||||
// set up listeners
|
||||
_audioPlayer.onPositionChanged.listen((Duration duration) {
|
||||
if(!_sliderMoving){
|
||||
_audioPosition = duration;
|
||||
rebuild();
|
||||
}
|
||||
//setState(() => position = p);
|
||||
});
|
||||
_audioPlayer.onPlayerStateChanged.listen((event) {
|
||||
//_audioPosition = _audioTime;
|
||||
rebuild();
|
||||
});
|
||||
_audioPlayer.onDurationChanged.listen((Duration duration) {
|
||||
_audioTime = duration;
|
||||
rebuild();
|
||||
});
|
||||
_audioPlayer.onSeekComplete.listen((event) {
|
||||
rebuild();
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
super.dispose();
|
||||
// _myPlayer.closeAudioSession();
|
||||
_audioPlayer.release();
|
||||
_audioPlayer.dispose();
|
||||
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
if(_audio != widget.audio){
|
||||
WidgetsBinding.instance.addPostFrameCallback((timeStamp) async {
|
||||
_audio = widget.audio;
|
||||
if(_isLocalFile){
|
||||
await _audioPlayer.setSourceDeviceFile(_audio);
|
||||
}else{
|
||||
await _audioPlayer.setSourceUrl(_audio);
|
||||
}
|
||||
_audioPlayer.seek(const Duration(milliseconds: 0));
|
||||
_audioPlayer.stop();
|
||||
rebuild();
|
||||
});
|
||||
}
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.end,
|
||||
children: [
|
||||
Row(
|
||||
children: [
|
||||
Material(
|
||||
color: Colors.transparent,
|
||||
child: _getAudioButton()
|
||||
),
|
||||
Expanded(
|
||||
child: Slider(
|
||||
value: _audioPosition?.inMilliseconds?.toDouble() ?? 0.0,
|
||||
min: 0,
|
||||
max: _audioTime?.inMilliseconds?.toDouble() ?? 60.0,
|
||||
onChangeStart: (value){
|
||||
_sliderMoving = true;
|
||||
},
|
||||
onChanged: (value){
|
||||
_audioPosition = Duration(milliseconds: value.round());
|
||||
rebuild();
|
||||
},
|
||||
onChangeEnd: (value){
|
||||
_sliderMoving = false;
|
||||
_audioPlayer.seek(Duration(milliseconds: value.round()));
|
||||
rebuild();
|
||||
}
|
||||
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: Visibility(
|
||||
visible: _failedToLoad,
|
||||
child: Row(
|
||||
children: [
|
||||
Text(
|
||||
"Failed to load",
|
||||
style: Theme.of(context).textTheme.overline.copyWith(
|
||||
color: AColors.red
|
||||
),
|
||||
textScaleFactor: AppStyle.getScaleFactor(context),
|
||||
),
|
||||
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
Visibility(
|
||||
visible: _audioPlayer.state != PlayerState.stopped,
|
||||
child: Text(
|
||||
"${format(_audioPosition)}/${format(_audioTime)}",
|
||||
style: Theme.of(context).textTheme.overline,
|
||||
textScaleFactor: AppStyle.getScaleFactor(context),
|
||||
),
|
||||
),
|
||||
],
|
||||
)
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -1,37 +0,0 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:test_sa/controllers/providers/api/status_drop_down/employee/employee_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/models/lookup.dart';
|
||||
import 'package:test_sa/views/widgets/loaders/loading_manager.dart';
|
||||
import 'package:test_sa/views/widgets/status/single_status_menu.dart';
|
||||
class EmployeeMenu extends StatelessWidget {
|
||||
final Function(Lookup) onSelect;
|
||||
final Lookup initialValue;
|
||||
|
||||
const EmployeeMenu({Key key, this.onSelect, this.initialValue}) : super(key: key);
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final settingProvider = Provider.of<SettingProvider>(context);
|
||||
final userProvider = Provider.of<UserProvider>(context);
|
||||
final menuProvider = Provider.of<EmployeesProvider>(context);
|
||||
return LoadingManager(
|
||||
isLoading: menuProvider.isLoading,
|
||||
isFailedLoading: menuProvider.items == null,
|
||||
stateCode: menuProvider.stateCode,
|
||||
onRefresh: () async {
|
||||
menuProvider.reset();
|
||||
await menuProvider.getData(
|
||||
user: userProvider.user,
|
||||
host: settingProvider.host
|
||||
);
|
||||
},
|
||||
child: SingleStatusMenu(
|
||||
initialStatus: initialValue,
|
||||
statuses: menuProvider.items,
|
||||
onSelect: onSelect,
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -1,37 +0,0 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:test_sa/controllers/providers/api/status_drop_down/gas_refill/gas_cylinder_size_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/models/lookup.dart';
|
||||
import 'package:test_sa/views/widgets/loaders/loading_manager.dart';
|
||||
import 'package:test_sa/views/widgets/status/single_status_menu.dart';
|
||||
class GasCylinderSizeMenu extends StatelessWidget {
|
||||
final Function(Lookup) onSelect;
|
||||
final Lookup initialValue;
|
||||
|
||||
const GasCylinderSizeMenu({Key key, this.onSelect, this.initialValue}) : super(key: key);
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final settingProvider = Provider.of<SettingProvider>(context);
|
||||
final userProvider = Provider.of<UserProvider>(context);
|
||||
final menuProvider = Provider.of<GasCylinderSizesProvider>(context);
|
||||
return LoadingManager(
|
||||
isLoading: menuProvider.isLoading,
|
||||
isFailedLoading: menuProvider.items == null,
|
||||
stateCode: menuProvider.stateCode,
|
||||
onRefresh: () async {
|
||||
menuProvider.reset();
|
||||
await menuProvider.getData(
|
||||
user: userProvider.user,
|
||||
host: settingProvider.host
|
||||
);
|
||||
},
|
||||
child: SingleStatusMenu(
|
||||
initialStatus: initialValue,
|
||||
statuses: menuProvider.items,
|
||||
onSelect: onSelect,
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -1,37 +0,0 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:test_sa/controllers/providers/api/status_drop_down/gas_refill/gas_types_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/models/lookup.dart';
|
||||
import 'package:test_sa/views/widgets/loaders/loading_manager.dart';
|
||||
import 'package:test_sa/views/widgets/status/single_status_menu.dart';
|
||||
class GasTypeMenu extends StatelessWidget {
|
||||
final Function(Lookup) onSelect;
|
||||
final Lookup initialValue;
|
||||
|
||||
const GasTypeMenu({Key key, this.onSelect, this.initialValue}) : super(key: key);
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final settingProvider = Provider.of<SettingProvider>(context);
|
||||
final userProvider = Provider.of<UserProvider>(context);
|
||||
final menuProvider = Provider.of<GasTypesProvider>(context);
|
||||
return LoadingManager(
|
||||
isLoading: menuProvider.isLoading,
|
||||
isFailedLoading: menuProvider.items == null,
|
||||
stateCode: menuProvider.stateCode,
|
||||
onRefresh: () async {
|
||||
menuProvider.reset();
|
||||
await menuProvider.getData(
|
||||
user: userProvider.user,
|
||||
host: settingProvider.host
|
||||
);
|
||||
},
|
||||
child: SingleStatusMenu(
|
||||
initialStatus: initialValue,
|
||||
statuses: menuProvider.items,
|
||||
onSelect: onSelect,
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -1,131 +0,0 @@
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_typeahead/flutter_typeahead.dart';
|
||||
import 'package:test_sa/models/lookup.dart';
|
||||
import 'package:test_sa/views/app_style/colors.dart';
|
||||
import 'package:test_sa/views/app_style/sizing.dart';
|
||||
class MultiStatusMenu extends StatefulWidget {
|
||||
final List<Lookup> statuses;
|
||||
final List<Lookup> initialSelectedStatus;
|
||||
final Function(List<Lookup>) onSelect;
|
||||
|
||||
const MultiStatusMenu({Key key, this.statuses, this.onSelect, this.initialSelectedStatus}) : super(key: key);
|
||||
@override
|
||||
_MultiStatusMenuState createState() => _MultiStatusMenuState();
|
||||
}
|
||||
|
||||
class _MultiStatusMenuState extends State<MultiStatusMenu> {
|
||||
|
||||
List<Lookup> _selectedStatus = [];
|
||||
TextEditingController _controller;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
_controller = TextEditingController();
|
||||
_selectedStatus.addAll(widget.initialSelectedStatus);
|
||||
super.initState();
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_controller.clear();
|
||||
super.dispose();
|
||||
}
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return
|
||||
Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Wrap(
|
||||
crossAxisAlignment: WrapCrossAlignment.start,
|
||||
alignment: WrapAlignment.start,
|
||||
runAlignment: WrapAlignment.start,
|
||||
children: List.generate(
|
||||
_selectedStatus.length,
|
||||
(index) {
|
||||
final status = _selectedStatus[index];
|
||||
return Container(
|
||||
height: 36 * AppStyle.getScaleFactor(context),
|
||||
margin: EdgeInsets.all(4 * AppStyle.getScaleFactor(context)),
|
||||
//padding: EdgeInsets.all(4 * AppStyle.getScaleFactor(context)),
|
||||
decoration: BoxDecoration(
|
||||
color: Theme.of(context).colorScheme.primary,
|
||||
borderRadius: BorderRadius.circular(8)
|
||||
),
|
||||
child: Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
const SizedBox(width: 12,),
|
||||
Text(
|
||||
status.label,
|
||||
style: Theme.of(context).textTheme.bodyText1.copyWith(
|
||||
color:Theme.of(context).colorScheme.onPrimary,
|
||||
),
|
||||
),
|
||||
IconButton(
|
||||
color:Theme.of(context).colorScheme.onPrimary,
|
||||
onPressed: (){
|
||||
_selectedStatus.remove(status);
|
||||
widget.onSelect(_selectedStatus);
|
||||
setState(() {});
|
||||
},
|
||||
icon: const Icon(Icons.delete)
|
||||
)
|
||||
],
|
||||
)
|
||||
);
|
||||
}
|
||||
),
|
||||
),
|
||||
Container(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: 16
|
||||
),
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white,
|
||||
border: Border.all(color:AColors.black),
|
||||
borderRadius: BorderRadius.circular(
|
||||
AppStyle.borderRadius * AppStyle.getScaleFactor(context)
|
||||
),
|
||||
boxShadow: const [
|
||||
AppStyle.boxShadow
|
||||
]
|
||||
),
|
||||
child: TypeAheadField<Lookup>(
|
||||
textFieldConfiguration: TextFieldConfiguration(
|
||||
style: Theme.of(context).textTheme.subtitle1,
|
||||
controller: _controller,
|
||||
textAlign: TextAlign.center,
|
||||
decoration: const InputDecoration(
|
||||
border: InputBorder.none,
|
||||
disabledBorder: InputBorder.none,
|
||||
focusedBorder: InputBorder.none,
|
||||
enabledBorder: InputBorder.none,
|
||||
),
|
||||
textInputAction: TextInputAction.search,
|
||||
),
|
||||
suggestionsCallback: (vale) {
|
||||
return widget.statuses.where((Lookup option) {
|
||||
return option.label.toLowerCase().contains(_controller.text);
|
||||
});
|
||||
},
|
||||
itemBuilder: (context, part) {
|
||||
return ListTile(
|
||||
title: Text(part.label),
|
||||
);
|
||||
},
|
||||
onSuggestionSelected: (status) {
|
||||
_controller.clear();
|
||||
if(!_selectedStatus.contains(status)){
|
||||
_selectedStatus.add(status);
|
||||
widget.onSelect(_selectedStatus);
|
||||
setState(() {});
|
||||
}
|
||||
},
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -1,37 +0,0 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:test_sa/controllers/providers/api/status_drop_down/pentry/pentry_status_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/models/lookup.dart';
|
||||
import 'package:test_sa/views/widgets/loaders/loading_manager.dart';
|
||||
import 'package:test_sa/views/widgets/status/single_status_menu.dart';
|
||||
class PentryStatusMenu extends StatelessWidget {
|
||||
final Function(Lookup) onSelect;
|
||||
final Lookup initialValue;
|
||||
|
||||
const PentryStatusMenu({Key key, this.onSelect, this.initialValue}) : super(key: key);
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final settingProvider = Provider.of<SettingProvider>(context);
|
||||
final userProvider = Provider.of<UserProvider>(context);
|
||||
final menuProvider = Provider.of<PentryStatusProvider>(context);
|
||||
return LoadingManager(
|
||||
isLoading: menuProvider.isLoading,
|
||||
isFailedLoading: menuProvider.items == null,
|
||||
stateCode: menuProvider.stateCode,
|
||||
onRefresh: () async {
|
||||
menuProvider.reset();
|
||||
await menuProvider.getData(
|
||||
user: userProvider.user,
|
||||
host: settingProvider.host
|
||||
);
|
||||
},
|
||||
child: SingleStatusMenu(
|
||||
initialStatus: initialValue,
|
||||
statuses: menuProvider.items,
|
||||
onSelect: onSelect,
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -1,37 +0,0 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:test_sa/controllers/providers/api/status_drop_down/pentry/pentry_task_status_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/models/lookup.dart';
|
||||
import 'package:test_sa/views/widgets/loaders/loading_manager.dart';
|
||||
import 'package:test_sa/views/widgets/status/single_status_menu.dart';
|
||||
class PentryTaskStatusMenu extends StatelessWidget {
|
||||
final Function(Lookup) onSelect;
|
||||
final Lookup initialValue;
|
||||
|
||||
const PentryTaskStatusMenu({Key key, this.onSelect, this.initialValue}) : super(key: key);
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final settingProvider = Provider.of<SettingProvider>(context);
|
||||
final userProvider = Provider.of<UserProvider>(context);
|
||||
final menuProvider = Provider.of<PentryTaskStatusProvider>(context);
|
||||
return LoadingManager(
|
||||
isLoading: menuProvider.isLoading,
|
||||
isFailedLoading: menuProvider.items == null,
|
||||
stateCode: menuProvider.stateCode,
|
||||
onRefresh: () async {
|
||||
menuProvider.reset();
|
||||
await menuProvider.getData(
|
||||
user: userProvider.user,
|
||||
host: settingProvider.host
|
||||
);
|
||||
},
|
||||
child: SingleStatusMenu(
|
||||
initialStatus: initialValue,
|
||||
statuses: menuProvider.items,
|
||||
onSelect: onSelect,
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -1,37 +0,0 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:test_sa/controllers/providers/api/status_drop_down/pentry/pentry_visit_status_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/models/lookup.dart';
|
||||
import 'package:test_sa/views/widgets/loaders/loading_manager.dart';
|
||||
import 'package:test_sa/views/widgets/status/single_status_menu.dart';
|
||||
class PentryVisitsStatusMenu extends StatelessWidget {
|
||||
final Function(Lookup) onSelect;
|
||||
final Lookup initialValue;
|
||||
|
||||
const PentryVisitsStatusMenu({Key key, this.onSelect, this.initialValue}) : super(key: key);
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final settingProvider = Provider.of<SettingProvider>(context);
|
||||
final userProvider = Provider.of<UserProvider>(context);
|
||||
final menuProvider = Provider.of<PentryVisitStatusProvider>(context);
|
||||
return LoadingManager(
|
||||
isLoading: menuProvider.isLoading,
|
||||
isFailedLoading: menuProvider.items == null,
|
||||
stateCode: menuProvider.stateCode,
|
||||
onRefresh: () async {
|
||||
menuProvider.reset();
|
||||
await menuProvider.getData(
|
||||
user: userProvider.user,
|
||||
host: settingProvider.host
|
||||
);
|
||||
},
|
||||
child: SingleStatusMenu(
|
||||
initialStatus: initialValue,
|
||||
statuses: menuProvider.items,
|
||||
onSelect: onSelect,
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -1,29 +0,0 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:test_sa/controllers/providers/api/status_drop_down/report/service_report_last_calls_provider.dart';
|
||||
import 'package:test_sa/models/lookup.dart';
|
||||
import 'package:test_sa/models/service_report.dart';
|
||||
import 'package:test_sa/views/widgets/loaders/loading_manager.dart';
|
||||
import 'package:test_sa/views/widgets/status/single_status_menu.dart';
|
||||
class ServiceReportLastCallsMenu extends StatelessWidget {
|
||||
final Function(Lookup) onSelect;
|
||||
final ServiceReport report;
|
||||
|
||||
const ServiceReportLastCallsMenu({
|
||||
Key key,@required this.onSelect,@required this.report}) : super(key: key);
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
ServiceReportLastCallsProvider _menuProvider = Provider.of<ServiceReportLastCallsProvider>(context);
|
||||
return LoadingManager(
|
||||
isLoading: _menuProvider.isLoading,
|
||||
isFailedLoading: _menuProvider.calls == null,
|
||||
stateCode: _menuProvider.stateCode,
|
||||
onRefresh: () async {},
|
||||
child: SingleStatusMenu(
|
||||
initialStatus: report?.callLastSituation,
|
||||
statuses: _menuProvider.calls,
|
||||
onSelect: onSelect,
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -1,38 +0,0 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:test_sa/controllers/providers/api/status_drop_down/report/service_report_reasons_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/models/lookup.dart';
|
||||
import 'package:test_sa/views/widgets/loaders/loading_manager.dart';
|
||||
import 'package:test_sa/views/widgets/status/single_status_menu.dart';
|
||||
class ServiceReportReasonsMenu extends StatelessWidget {
|
||||
final Lookup initialValue;
|
||||
final Function(Lookup) onSelect;
|
||||
|
||||
const ServiceReportReasonsMenu({Key key, this.onSelect, this.initialValue}) : super(key: key);
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
SettingProvider _settingProvider = Provider.of<SettingProvider>(context);
|
||||
UserProvider _userProvider = Provider.of<UserProvider>(context);
|
||||
ServiceReportReasonsProvider _menuProvider = Provider.of<ServiceReportReasonsProvider>(context);
|
||||
return LoadingManager(
|
||||
isLoading: _menuProvider.isLoading,
|
||||
isFailedLoading: _menuProvider.reasons == null,
|
||||
stateCode: _menuProvider.stateCode,
|
||||
onRefresh: () async {
|
||||
_menuProvider.reset();
|
||||
await _menuProvider.getTypes(
|
||||
user: _userProvider.user,
|
||||
host: _settingProvider.host,
|
||||
|
||||
);
|
||||
},
|
||||
child: SingleStatusMenu(
|
||||
initialStatus: initialValue,
|
||||
statuses: _menuProvider.reasons,
|
||||
onSelect: onSelect,
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -1,70 +0,0 @@
|
||||
import 'dart:math';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:provider/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_report_status_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/models/lookup.dart';
|
||||
import 'package:test_sa/models/service_report.dart';
|
||||
import 'package:test_sa/views/widgets/loaders/loading_manager.dart';
|
||||
import 'package:test_sa/views/widgets/status/single_status_menu.dart';
|
||||
class ServiceReportStatusMenu extends StatefulWidget {
|
||||
final Function(Lookup) onSelect;
|
||||
final ServiceReport report;
|
||||
|
||||
const ServiceReportStatusMenu({Key key, this.onSelect, this.report}) : super(key: key);
|
||||
|
||||
@override
|
||||
State<ServiceReportStatusMenu> createState() => _ServiceReportStatusMenuState();
|
||||
}
|
||||
|
||||
class _ServiceReportStatusMenuState extends State<ServiceReportStatusMenu> {
|
||||
bool firstTime = true;
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
SettingProvider _settingProvider = Provider.of<SettingProvider>(context);
|
||||
UserProvider _userProvider = Provider.of<UserProvider>(context);
|
||||
ServiceReportStatusProvider _menuProvider = Provider.of<ServiceReportStatusProvider>(context);
|
||||
ServiceReportLastCallsProvider _callsLastSituationsProvider = Provider.of<ServiceReportLastCallsProvider>(context,listen: false);
|
||||
if(firstTime){
|
||||
_callsLastSituationsProvider.reset();
|
||||
|
||||
firstTime = false;
|
||||
}
|
||||
return LoadingManager(
|
||||
isLoading: _menuProvider.isLoading == true || _callsLastSituationsProvider.isLoading == true,
|
||||
isFailedLoading: _menuProvider.statuses == null || _callsLastSituationsProvider.calls == null,
|
||||
stateCode: _menuProvider.stateCode == null || _callsLastSituationsProvider.stateCode == null ? null:
|
||||
max(_menuProvider.stateCode ?? 0,_callsLastSituationsProvider.stateCode ?? 0),
|
||||
onRefresh: () async {
|
||||
if(_menuProvider.stateCode == null){
|
||||
_menuProvider.reset();
|
||||
await _menuProvider.getTypes(
|
||||
user: _userProvider.user,
|
||||
host: _settingProvider.host
|
||||
);
|
||||
}
|
||||
await _callsLastSituationsProvider.getCalls(
|
||||
user: _userProvider.user,
|
||||
host: _settingProvider.host,
|
||||
serviceStatus: widget.report.status?.id.toString()
|
||||
);
|
||||
},
|
||||
child: SingleStatusMenu(
|
||||
statuses: _menuProvider.statuses,
|
||||
initialStatus: widget.report.status,
|
||||
onSelect: (status){
|
||||
_callsLastSituationsProvider.getCalls(
|
||||
user: _userProvider.user,
|
||||
host: _settingProvider.host,
|
||||
serviceStatus: status.id.toString()
|
||||
);
|
||||
widget.report.callLastSituation = null;
|
||||
widget.onSelect(status);
|
||||
},
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -1,37 +0,0 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:test_sa/controllers/providers/api/status_drop_down/report/service_types_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/models/lookup.dart';
|
||||
import 'package:test_sa/views/widgets/loaders/loading_manager.dart';
|
||||
import 'package:test_sa/views/widgets/status/single_status_menu.dart';
|
||||
class ServiceStatusMenu extends StatelessWidget {
|
||||
final Function(Lookup) onSelect;
|
||||
final Lookup initialValue;
|
||||
|
||||
const ServiceStatusMenu({Key key, this.onSelect, this.initialValue}) : super(key: key);
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
SettingProvider _settingProvider = Provider.of<SettingProvider>(context);
|
||||
UserProvider _userProvider = Provider.of<UserProvider>(context);
|
||||
ServiceStatusProvider _menuProvider = Provider.of<ServiceStatusProvider>(context);
|
||||
return LoadingManager(
|
||||
isLoading: _menuProvider.isLoading,
|
||||
isFailedLoading: _menuProvider.statuses == null,
|
||||
stateCode: _menuProvider.stateCode,
|
||||
onRefresh: () async {
|
||||
_menuProvider.reset();
|
||||
await _menuProvider.getTypes(
|
||||
user: _userProvider.user,
|
||||
host: _settingProvider.host
|
||||
);
|
||||
},
|
||||
child: SingleStatusMenu(
|
||||
initialStatus: initialValue,
|
||||
statuses: _menuProvider.statuses,
|
||||
onSelect: onSelect,
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -1,37 +0,0 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:test_sa/controllers/providers/api/status_drop_down/report/service_report_defect_types_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/models/lookup.dart';
|
||||
import 'package:test_sa/views/widgets/loaders/loading_manager.dart';
|
||||
import 'package:test_sa/views/widgets/status/single_status_menu.dart';
|
||||
class ServiceRequestDefectTypesMenu extends StatelessWidget {
|
||||
final Function(Lookup) onSelect;
|
||||
final Lookup initialValue;
|
||||
|
||||
const ServiceRequestDefectTypesMenu({Key key, this.onSelect, this.initialValue}) : super(key: key);
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final settingProvider = Provider.of<SettingProvider>(context);
|
||||
final userProvider = Provider.of<UserProvider>(context);
|
||||
final menuProvider = Provider.of<ServiceRequestDefectTypesProvider>(context);
|
||||
return LoadingManager(
|
||||
isLoading: menuProvider.isLoading,
|
||||
isFailedLoading: menuProvider.items == null,
|
||||
stateCode: menuProvider.stateCode,
|
||||
onRefresh: () async {
|
||||
menuProvider.reset();
|
||||
await menuProvider.getData(
|
||||
user: userProvider.user,
|
||||
host: settingProvider.host
|
||||
);
|
||||
},
|
||||
child: SingleStatusMenu(
|
||||
initialStatus: initialValue,
|
||||
statuses: menuProvider.items,
|
||||
onSelect: onSelect,
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -1,37 +0,0 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:test_sa/controllers/providers/api/status_drop_down/report/service_report_priority_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/models/lookup.dart';
|
||||
import 'package:test_sa/views/widgets/loaders/loading_manager.dart';
|
||||
import 'package:test_sa/views/widgets/status/single_status_menu.dart';
|
||||
class ServiceRequestPriorityMenu extends StatelessWidget {
|
||||
final Function(Lookup) onSelect;
|
||||
final Lookup initialValue;
|
||||
|
||||
const ServiceRequestPriorityMenu({Key key, this.onSelect, this.initialValue}) : super(key: key);
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final settingProvider = Provider.of<SettingProvider>(context);
|
||||
final userProvider = Provider.of<UserProvider>(context);
|
||||
final menuProvider = Provider.of<ServiceRequestPriorityProvider>(context);
|
||||
return LoadingManager(
|
||||
isLoading: menuProvider.isLoading,
|
||||
isFailedLoading: menuProvider.items == null,
|
||||
stateCode: menuProvider.stateCode,
|
||||
onRefresh: () async {
|
||||
menuProvider.reset();
|
||||
await menuProvider.getData(
|
||||
user: userProvider.user,
|
||||
host: settingProvider.host
|
||||
);
|
||||
},
|
||||
child: SingleStatusMenu(
|
||||
initialStatus: initialValue,
|
||||
statuses: menuProvider.items,
|
||||
onSelect: onSelect,
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -1,131 +0,0 @@
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:test_sa/models/timer_model.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/loaders/app_loading.dart';
|
||||
class AppTimer extends StatefulWidget {
|
||||
final TimerModel timer;
|
||||
final Future<bool> Function(TimerModel) onChange;
|
||||
final TextStyle style;
|
||||
const AppTimer({
|
||||
Key key,
|
||||
this.timer,
|
||||
this.onChange,
|
||||
this.style,
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
State<AppTimer> createState() => _AppTimerState();
|
||||
}
|
||||
|
||||
class _AppTimerState extends State<AppTimer> {
|
||||
Timer _timer;
|
||||
DateTime _startAt;
|
||||
DateTime _endAt;
|
||||
int _delay = 0;
|
||||
bool _running = false;
|
||||
bool _loading = false;
|
||||
final ValueNotifier<String> _period = ValueNotifier("0:00:00");
|
||||
|
||||
_startTimer() async {
|
||||
if (!_running) {
|
||||
final time = DateTime.now();
|
||||
bool result = await widget.onChange(
|
||||
TimerModel(startAt: time,endAt: null,durationInSecond: _delay));
|
||||
if(!result) return;
|
||||
_running = true;
|
||||
|
||||
if(_endAt != null){
|
||||
_delay += _endAt.difference(_startAt).inSeconds;
|
||||
}
|
||||
_startAt = time.subtract(Duration(seconds: _delay));
|
||||
_endAt = null;
|
||||
}
|
||||
|
||||
_timer = Timer.periodic(const Duration(seconds: 1), (timer) {
|
||||
if(_loading == true) return;
|
||||
_period.value = (_endAt ?? DateTime.now()).difference(
|
||||
_startAt
|
||||
).toString().split(".").first;
|
||||
});
|
||||
}
|
||||
|
||||
_stopTimer() async {
|
||||
final time = DateTime.now();
|
||||
final tempStartAt = _startAt.add(Duration(seconds: _delay));
|
||||
bool result = await widget.onChange(
|
||||
TimerModel(startAt: tempStartAt,endAt: time,durationInSecond: _delay));
|
||||
if(!result) return;
|
||||
_running = false;
|
||||
_endAt = time;
|
||||
_startAt = tempStartAt;
|
||||
_timer?.cancel();
|
||||
}
|
||||
|
||||
_onPressed() async {
|
||||
_loading = true;
|
||||
setState(() {});
|
||||
if(!_running){
|
||||
await _startTimer();
|
||||
}else{
|
||||
await _stopTimer();
|
||||
}
|
||||
_loading = false;
|
||||
setState(() {});
|
||||
}
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
_startAt = widget.timer?.startAt;
|
||||
_endAt = widget.timer?.endAt;
|
||||
_running = _startAt != null && _endAt == null;
|
||||
_delay = (widget.timer?.durationInSecond ?? 0);
|
||||
final difference = _startAt == null ? 0:
|
||||
(_endAt ?? DateTime.now())?.difference(_startAt)?.inSeconds ?? 0;
|
||||
_period.value = Duration(seconds: _running ? difference : _delay + difference).toString().split(".").first;
|
||||
super.initState();
|
||||
if(_running){_startTimer();}
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
super.dispose();
|
||||
}
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return SizedBox(
|
||||
width: 100 * AppStyle.getScaleFactor(context),
|
||||
height: 28 * AppStyle.getScaleFactor(context),
|
||||
child: ElevatedButton(
|
||||
style: ElevatedButton.styleFrom(
|
||||
minimumSize: const Size(1, 1),
|
||||
padding: EdgeInsets.all(4 * AppStyle.getScaleFactor(context)),
|
||||
backgroundColor: _running ? AColors.green[300] : AColors.grey,
|
||||
foregroundColor: Colors.black
|
||||
),
|
||||
onPressed: _loading ? null : _onPressed,
|
||||
child: _loading ? const SizedBox.square(
|
||||
dimension: 18,child: CircularProgressIndicator(color: Colors.white,)):
|
||||
Row(
|
||||
children: [
|
||||
Icon(_running ? Icons.pause : Icons.play_arrow),
|
||||
Expanded(
|
||||
child: Center(
|
||||
child: ValueListenableBuilder<String>(
|
||||
valueListenable: _period,
|
||||
builder: (context,value,_){
|
||||
return Text(value,
|
||||
style: widget.style,
|
||||
);
|
||||
}
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -1,26 +0,0 @@
|
||||
import 'package:test_sa/views/app_style/sizing.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
class ATitle extends StatelessWidget {
|
||||
final String text;
|
||||
final EdgeInsets padding;
|
||||
final bool center;
|
||||
const ATitle(this.text, {Key key,this.padding,this.center= false}) : super(key: key);
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Padding(
|
||||
padding: padding ?? EdgeInsets.symmetric(horizontal: 16,vertical: 8),
|
||||
child: Row(
|
||||
mainAxisAlignment: center
|
||||
? MainAxisAlignment.center
|
||||
: MainAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
text,
|
||||
style: Theme.of(context).textTheme.headline6,
|
||||
textScaleFactor: AppStyle.getScaleFactor(context),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -1,93 +0,0 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
|
||||
import 'package:test_sa/views/app_style/sizing.dart';
|
||||
class ExpandableInfoRow extends StatefulWidget {
|
||||
final IconData iconData;
|
||||
final String title;
|
||||
final Widget child;
|
||||
|
||||
const ExpandableInfoRow({Key key, this.iconData, this.title, this.child}) : super(key: key);
|
||||
|
||||
@override
|
||||
_ExpandableInfoRowState createState() => _ExpandableInfoRowState();
|
||||
}
|
||||
|
||||
class _ExpandableInfoRowState extends State<ExpandableInfoRow>
|
||||
with TickerProviderStateMixin{
|
||||
bool _isExpanded = false;
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return InkWell(
|
||||
onTap: (){
|
||||
_isExpanded = !_isExpanded;
|
||||
setState(() {});
|
||||
},
|
||||
child: Column(
|
||||
children: [
|
||||
Row(
|
||||
children: <Widget>[
|
||||
widget.iconData != null ?
|
||||
Padding(
|
||||
padding: EdgeInsets.symmetric(
|
||||
horizontal: 8 * AppStyle.getScaleFactor(context),
|
||||
vertical: 2 * AppStyle.getScaleFactor(context),
|
||||
),
|
||||
child: FaIcon(
|
||||
widget.iconData,
|
||||
color: Theme.of(context).primaryColor,
|
||||
size: 20 * AppStyle.getScaleFactor(context),
|
||||
),
|
||||
):SizedBox.shrink(),
|
||||
Expanded(
|
||||
flex: 2,
|
||||
child: Text(
|
||||
widget.title,
|
||||
style: TextStyle(
|
||||
//color: Theme.of(context).dividerColor,
|
||||
fontSize: 14,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
textScaleFactor: AppStyle.getScaleFactor(context),
|
||||
),
|
||||
),
|
||||
AnimatedSwitcher(
|
||||
duration: Duration(milliseconds: 400),
|
||||
transitionBuilder: (Widget child, Animation<double> animation) {
|
||||
return FadeTransition(
|
||||
child: ScaleTransition(
|
||||
child: child,
|
||||
scale: animation
|
||||
),
|
||||
opacity: animation,
|
||||
);
|
||||
},
|
||||
child: Icon(
|
||||
_isExpanded
|
||||
? Icons.keyboard_arrow_up
|
||||
: Icons.keyboard_arrow_down,
|
||||
key: ValueKey(_isExpanded
|
||||
? "Icons.keyboard_arrow_up"
|
||||
: "Icons.keyboard_arrow_down"),
|
||||
color: Theme.of(context).primaryColor,
|
||||
size: 24 * AppStyle.getScaleFactor(context),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
AnimatedSize(
|
||||
duration: Duration(milliseconds: 300),
|
||||
child: Visibility(
|
||||
visible: _isExpanded,
|
||||
child: Padding(
|
||||
padding: EdgeInsets.symmetric(vertical: 8 * AppStyle.getScaleFactor(context)),
|
||||
child: widget.child,
|
||||
)
|
||||
),
|
||||
),
|
||||
Divider(height: 2 * AppStyle.getScaleFactor(context),),
|
||||
SizedBox(height: 8 * AppStyle.getScaleFactor(context),),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -1,44 +0,0 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:test_sa/models/visits/visit.dart';
|
||||
import 'package:test_sa/views/app_style/colors.dart';
|
||||
import 'package:test_sa/views/app_style/sizing.dart';
|
||||
class VisitStatusLabel extends StatelessWidget {
|
||||
final Visit visit;
|
||||
|
||||
const VisitStatusLabel({Key key, this.visit}) : super(key: key);
|
||||
|
||||
Color getStatusColor(){
|
||||
switch(visit.status.id){
|
||||
case 0: return AColors.green;
|
||||
case 1: return AColors.grey;
|
||||
case 2: return AColors.grey;
|
||||
default : return AColors.grey;
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Container(
|
||||
padding: EdgeInsets.symmetric(vertical: 2,horizontal: 8),
|
||||
alignment: Alignment.center,
|
||||
decoration: BoxDecoration(
|
||||
color: getStatusColor(),
|
||||
borderRadius: BorderRadius.circular(
|
||||
AppStyle.getBorderRadius(context)
|
||||
),
|
||||
boxShadow: [
|
||||
AppStyle.boxShadow
|
||||
]
|
||||
),
|
||||
child: Text(
|
||||
visit.status.label == null
|
||||
|| visit.status.label.isEmpty
|
||||
? "no status" :visit.status.label,
|
||||
style: Theme.of(context).textTheme.subtitle2.copyWith(
|
||||
color: getStatusColor().computeLuminance() > 0.5
|
||||
? AColors.black : Colors.white,
|
||||
),
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,38 @@
|
||||
import '../../models/subtitle.dart';
|
||||
|
||||
class HttpStatusManger {
|
||||
static String getStatusMessage({
|
||||
required int? status,
|
||||
required Subtitle? subtitle,
|
||||
String? messageFor400,
|
||||
String? messageFor200,
|
||||
}) {
|
||||
if (status == null) {
|
||||
return "careful null status";
|
||||
}
|
||||
if (status == -1) {
|
||||
return subtitle?.currentlyServiceNotAvailable??"";
|
||||
}
|
||||
if (status == -2) {
|
||||
// client's request in process
|
||||
return subtitle?.waitUntilYourRequestComplete??"";
|
||||
} else if (status >= 200 && status < 300) {
|
||||
// client's request was successfully received
|
||||
return messageFor200 ?? subtitle?.requestCompleteSuccessfully??"";
|
||||
} else if (status >= 400 && status < 500) {
|
||||
// client's request have error
|
||||
switch (status) {
|
||||
case 400:
|
||||
return messageFor400 ?? subtitle?.failedToCompleteRequest??"";
|
||||
default:
|
||||
return subtitle?.failedToCompleteRequest??"";
|
||||
}
|
||||
} else if (status >= 500) {
|
||||
// server error
|
||||
return subtitle?.currentlyServiceNotAvailable??"";
|
||||
} else {
|
||||
// no error match so return default error
|
||||
return subtitle?.failedToCompleteRequest??"";
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,165 @@
|
||||
import 'dart:convert';
|
||||
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:http/http.dart';
|
||||
|
||||
import '../../../models/gas_refill/gas_refill_model.dart';
|
||||
import '../../../models/user.dart';
|
||||
import '../../api_routes/urls.dart';
|
||||
|
||||
class GasRefillProvider extends ChangeNotifier {
|
||||
// number of items call in each request
|
||||
final pageItemNumber = 50;
|
||||
|
||||
//reset provider data
|
||||
void reset() {
|
||||
items = null;
|
||||
nextPage = true;
|
||||
stateCode = null;
|
||||
}
|
||||
|
||||
// state code of current request to defied error message
|
||||
// like 400 customer request failed
|
||||
// 500 service not available
|
||||
int? stateCode;
|
||||
|
||||
// true if there is next page in product list and false if not
|
||||
bool nextPage = true;
|
||||
|
||||
// list of user requests
|
||||
List<GasRefillModel>? items;
|
||||
|
||||
// when requests in-process _loading = true
|
||||
// done _loading = true
|
||||
// failed _loading = false
|
||||
bool? isLoading;
|
||||
|
||||
/// return -2 if request in progress
|
||||
/// return -1 if error happen when sending request
|
||||
/// 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> getRequests({
|
||||
required String host,
|
||||
required User user,
|
||||
}) async {
|
||||
if (isLoading == true) {
|
||||
return -2;
|
||||
}
|
||||
isLoading = true;
|
||||
Response response;
|
||||
try {
|
||||
response = await get(
|
||||
Uri.parse("$host${URLs.getGasRefill}?uid=${user.id}"
|
||||
"&token=${user.token}&page=${(items?.length ?? 0) ~/ pageItemNumber}"),
|
||||
headers: {"Content-Type": "application/json; charset=utf-8"});
|
||||
stateCode = response.statusCode;
|
||||
if (stateCode != null && stateCode! >= 200 && stateCode! < 300) {
|
||||
// client's request was successfully received
|
||||
List requestsListJson = json.decode(utf8.decode(response.bodyBytes));
|
||||
List<GasRefillModel> itemsPage = requestsListJson
|
||||
.map((request) => GasRefillModel.fromJson(request))
|
||||
.toList();
|
||||
items ??= [];
|
||||
items?.addAll(itemsPage);
|
||||
if (itemsPage.length == pageItemNumber) {
|
||||
nextPage = true;
|
||||
} else {
|
||||
nextPage = false;
|
||||
}
|
||||
}
|
||||
isLoading = false;
|
||||
notifyListeners();
|
||||
return response.statusCode;
|
||||
} catch (error) {
|
||||
isLoading = false;
|
||||
stateCode = -1;
|
||||
notifyListeners();
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
Future<int> createModel({
|
||||
required String host,
|
||||
required User user,
|
||||
required GasRefillModel model,
|
||||
}) async {
|
||||
Map<String, dynamic> body = {
|
||||
"uid": user.id.toString(),
|
||||
"token": user.token ?? "",
|
||||
"title": model.title ?? "",
|
||||
"status": "0", //model.status.value.toString(),
|
||||
};
|
||||
|
||||
body["details"] = jsonEncode(model.details
|
||||
?.map((model) => {
|
||||
"type": model.type?.id.toString(),
|
||||
"size": model.cylinderSize?.id.toString(),
|
||||
"requsted_qty": model.requestedQuantity.toString(),
|
||||
})
|
||||
.toList());
|
||||
|
||||
Response response;
|
||||
try {
|
||||
response = await post(
|
||||
Uri.parse(host + URLs.requestGasRefill),
|
||||
body: body,
|
||||
);
|
||||
|
||||
stateCode = response.statusCode;
|
||||
if (response.statusCode >= 200 && response.statusCode < 300) {
|
||||
final items = this.items;
|
||||
if (items != null) {
|
||||
items.insert(
|
||||
0,
|
||||
GasRefillModel.fromJson(
|
||||
json.decode(utf8.decode(response.bodyBytes))[0]));
|
||||
notifyListeners();
|
||||
}
|
||||
}
|
||||
return response.statusCode;
|
||||
} catch (error) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
Future<int> updateModel({
|
||||
required String host,
|
||||
required User user,
|
||||
required GasRefillModel? oldModel,
|
||||
required GasRefillModel newModel,
|
||||
}) async {
|
||||
Map<String, dynamic> body = {
|
||||
"uid": user.id.toString(),
|
||||
"token": user.token,
|
||||
"title": newModel.title ?? "",
|
||||
"status": newModel.status?.id.toString(),
|
||||
};
|
||||
|
||||
body["details"] = jsonEncode(newModel.details
|
||||
?.map((model) => {
|
||||
"type": model.type?.id.toString(),
|
||||
"size": model.cylinderSize?.id.toString(),
|
||||
"requsted_qty": model.requestedQuantity.toString(),
|
||||
"deliverd_qty": model.deliveredQuantity.toString(),
|
||||
})
|
||||
.toList());
|
||||
|
||||
Response response;
|
||||
try {
|
||||
response = await post(
|
||||
Uri.parse("$host${URLs.updateGasRefill}/${newModel.id}"),
|
||||
body: body,
|
||||
);
|
||||
|
||||
stateCode = response.statusCode;
|
||||
if (response.statusCode >= 200 && response.statusCode < 300) {
|
||||
oldModel?.fromGasRefillModel(newModel);
|
||||
notifyListeners();
|
||||
}
|
||||
return response.statusCode;
|
||||
} catch (error) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,378 @@
|
||||
import 'dart:convert';
|
||||
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:http/http.dart';
|
||||
|
||||
import '../../../models/issue.dart';
|
||||
import '../../../models/lookup.dart';
|
||||
import '../../../models/service_report.dart';
|
||||
import '../../../models/service_request/service_request.dart';
|
||||
import '../../../models/service_request/service_request_search.dart';
|
||||
import '../../../models/subtitle.dart';
|
||||
import '../../../models/timer_model.dart';
|
||||
import '../../../models/user.dart';
|
||||
import '../../api_routes/urls.dart';
|
||||
import '../../http_status_manger/http_status_manger.dart';
|
||||
|
||||
class ServiceRequestsProvider extends ChangeNotifier {
|
||||
// number of items call in each request
|
||||
final pageItemNumber = 50;
|
||||
|
||||
//reset provider data
|
||||
void reset() {
|
||||
serviceRequests = null;
|
||||
nextPage = true;
|
||||
stateCode = null;
|
||||
}
|
||||
|
||||
// state code of current request to defied error message
|
||||
// like 400 customer request failed
|
||||
// 500 service not available
|
||||
int? stateCode;
|
||||
|
||||
// true if there is next page in product list and false if not
|
||||
bool? nextPage = true;
|
||||
|
||||
// list of user requests
|
||||
List<ServiceRequest>? serviceRequests;
|
||||
|
||||
// when requests in-process _loading = true
|
||||
// done _loading = true
|
||||
// failed _loading = false
|
||||
bool? isLoading;
|
||||
|
||||
ServiceRequestSearch? search = ServiceRequestSearch();
|
||||
|
||||
/// return -2 if request in progress
|
||||
/// return -1 if error happen when sending request
|
||||
/// 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> getRequests({
|
||||
required String host,
|
||||
required User user,
|
||||
required String? hospitalId,
|
||||
}) async {
|
||||
if (isLoading == true) {
|
||||
return -2;
|
||||
}
|
||||
isLoading = true;
|
||||
Response response;
|
||||
try {
|
||||
response = await get(
|
||||
Uri.parse(
|
||||
"$host${URLs.getServiceRequests}?uid=${user.id}${hospitalId == null ? "" : "&client_nid=$hospitalId"}&token=${user.token}&page=${(serviceRequests?.length ?? 0) ~/ pageItemNumber}${search?.toSearchString()}",
|
||||
),
|
||||
headers: {"Content-Type": "application/json; charset=utf-8"},
|
||||
);
|
||||
stateCode = response.statusCode;
|
||||
if (response.statusCode >= 200 && response.statusCode < 300) {
|
||||
// client's request was successfully received
|
||||
List requestsListJson =
|
||||
json.decode(utf8.decode(response.bodyBytes).replaceAll("\\", ""));
|
||||
List<ServiceRequest> _serviceRequestsPage = requestsListJson
|
||||
.map((request) => ServiceRequest.fromJson(request))
|
||||
.toList();
|
||||
serviceRequests ??= [];
|
||||
serviceRequests?.addAll(_serviceRequestsPage);
|
||||
if (_serviceRequestsPage.length == pageItemNumber) {
|
||||
nextPage = true;
|
||||
} else {
|
||||
nextPage = false;
|
||||
}
|
||||
}
|
||||
isLoading = false;
|
||||
notifyListeners();
|
||||
return response.statusCode;
|
||||
} catch (error) {
|
||||
isLoading = false;
|
||||
stateCode = -1;
|
||||
notifyListeners();
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
Future<ServiceRequest> getSingleServiceRequest({
|
||||
required String requestId,
|
||||
required String host,
|
||||
required User user,
|
||||
required Subtitle subtitle,
|
||||
}) async {
|
||||
String userData = '';
|
||||
userData += "&uid=${user.id}";
|
||||
userData += "&token=${user.token}";
|
||||
|
||||
Response response;
|
||||
try {
|
||||
response = await get(Uri.parse(
|
||||
'$host${URLs.getSingleServiceRequest}?call_nid=$requestId$userData',
|
||||
));
|
||||
} catch (error) {
|
||||
throw (HttpStatusManger.getStatusMessage(status: -1, subtitle: subtitle) ?? '');
|
||||
}
|
||||
|
||||
// If the call to the server was successful, parse the JSON.
|
||||
if (response.statusCode >= 200 && response.statusCode < 300) {
|
||||
// If the call to the server was successful, parse the JSON.
|
||||
List jsonList =
|
||||
json.decode(utf8.decode(response.bodyBytes).replaceAll("\\", ""));
|
||||
List<ServiceRequest> requests =
|
||||
jsonList.map((i) => ServiceRequest.fromJson(i)).toList();
|
||||
return requests[0];
|
||||
} else {
|
||||
throw (HttpStatusManger.getStatusMessage(
|
||||
status: response.statusCode, subtitle: subtitle) ?? "");
|
||||
}
|
||||
}
|
||||
|
||||
Future<int> createRequest({
|
||||
required String host,
|
||||
required User user,
|
||||
required ServiceRequest serviceRequest,
|
||||
}) async {
|
||||
var body = {
|
||||
"uid": user.id,
|
||||
"token": user.token ?? "",
|
||||
"sn_id": serviceRequest.deviceId ?? "",
|
||||
"date": (DateTime.now().millisecondsSinceEpoch).toString(),
|
||||
"client": user.hospital?.id ?? '',
|
||||
"complaint": serviceRequest.maintenanceIssue,
|
||||
"image": json.encode(serviceRequest.devicePhotos),
|
||||
"priority": (serviceRequest.priority?.id).toString(),
|
||||
"defect_types": (serviceRequest.defectType?.id).toString(),
|
||||
};
|
||||
body["audio"] = serviceRequest.audio;
|
||||
Response response;
|
||||
try {
|
||||
response = await post(
|
||||
Uri.parse(host + URLs.createRequest),
|
||||
body: body,
|
||||
);
|
||||
stateCode = response.statusCode;
|
||||
if (response.statusCode >= 200 && response.statusCode < 300) {
|
||||
final serviceRequests = this.serviceRequests;
|
||||
if (serviceRequests != null) {
|
||||
serviceRequests.insert(
|
||||
0,
|
||||
ServiceRequest.fromJson(
|
||||
json.decode(utf8.decode(response.bodyBytes))[0],
|
||||
),
|
||||
);
|
||||
}
|
||||
notifyListeners();
|
||||
}
|
||||
return response.statusCode;
|
||||
} catch (error) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
Future<int> createIssueReport({
|
||||
required String host,
|
||||
required User user,
|
||||
required Issue issue,
|
||||
}) async {
|
||||
Response response;
|
||||
Map<String, String> body = issue.toMap();
|
||||
body["uid"] = user.id??"";
|
||||
body["token"] = user.token??"";
|
||||
try {
|
||||
response = await post(
|
||||
Uri.parse(host + URLs.createReport),
|
||||
body: body,
|
||||
);
|
||||
|
||||
stateCode = response.statusCode;
|
||||
if (response.statusCode >= 200 && response.statusCode < 300) {}
|
||||
return response.statusCode;
|
||||
} catch (error) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
Future<int> updateDate({
|
||||
required String? host,
|
||||
required User? user,
|
||||
required String? newDate,
|
||||
required Lookup? employee,
|
||||
required ServiceRequest? request,
|
||||
}) async {
|
||||
Response response;
|
||||
Map<String, String> body = {};
|
||||
body["uid"] = user?.id ?? '';
|
||||
body["token"] = user?.token ?? '';
|
||||
body["nid"] = request?.id ?? '';
|
||||
body["date"] = newDate ?? '';
|
||||
body["ass_emp"] = employee?.id.toString() ?? '';
|
||||
try {
|
||||
response = await post(
|
||||
Uri.parse((host ?? '') + URLs.updateRequestDate),
|
||||
body: body,
|
||||
);
|
||||
stateCode = response.statusCode;
|
||||
if (response.statusCode >= 200 && response.statusCode < 300) {
|
||||
request?.engineerName = employee?.label;
|
||||
notifyListeners();
|
||||
}
|
||||
return response.statusCode;
|
||||
} catch (error) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
Future<int> createServiceReport({
|
||||
required String host,
|
||||
required User user,
|
||||
required ServiceReport report,
|
||||
required ServiceRequest request,
|
||||
}) async {
|
||||
Response response;
|
||||
Map<String, String> body = report.toMap();
|
||||
body["uid"] = user.id??"";
|
||||
body["token"] = user.token??"";
|
||||
body["job_id"] = request.id ?? '';
|
||||
try {
|
||||
response = await post(
|
||||
Uri.parse(host + URLs.createServiceReport),
|
||||
body: body,
|
||||
);
|
||||
|
||||
stateCode = response.statusCode;
|
||||
if (response.statusCode >= 200 && response.statusCode < 300) {
|
||||
reset();
|
||||
notifyListeners();
|
||||
}
|
||||
return response.statusCode;
|
||||
} catch (error) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
Future<int> createDuplicatedReport({
|
||||
required String host,
|
||||
required User user,
|
||||
required ServiceRequest request,
|
||||
}) async {
|
||||
Response response;
|
||||
String userData = '';
|
||||
userData += "&uid=${user.id}";
|
||||
userData += "&token=${user.token}";
|
||||
|
||||
try {
|
||||
response = await get(
|
||||
Uri.parse(
|
||||
"$host${URLs.createDuplicatedReport}?nid=${request.id}$userData",
|
||||
),
|
||||
);
|
||||
|
||||
stateCode = response.statusCode;
|
||||
|
||||
if (response.statusCode >= 200 && response.statusCode < 300) {
|
||||
reset();
|
||||
notifyListeners();
|
||||
}
|
||||
return response.statusCode;
|
||||
} catch (error) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
Future<int> updateServiceReport({
|
||||
required String host,
|
||||
required User user,
|
||||
required ServiceReport report,
|
||||
required ServiceRequest request,
|
||||
}) async {
|
||||
Response response;
|
||||
Map<String, String> body = report.toMap();
|
||||
body["uid"] = user.id??"";
|
||||
body["token"] = user.token??"";
|
||||
body["job_id"] = request.id ?? '';
|
||||
body["report_id"] = request.reportID ?? '';
|
||||
try {
|
||||
response = await post(
|
||||
Uri.parse(host + URLs.updateServiceReport),
|
||||
body: body,
|
||||
);
|
||||
stateCode = response.statusCode;
|
||||
|
||||
if (response.statusCode >= 200 && response.statusCode < 300) {
|
||||
reset();
|
||||
notifyListeners();
|
||||
}
|
||||
return response.statusCode;
|
||||
} catch (error) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
Future<int> updateServiceReportTimer({
|
||||
required String host,
|
||||
required User user,
|
||||
required TimerModel timer,
|
||||
required ServiceRequest request,
|
||||
}) async {
|
||||
Response response;
|
||||
Map<String, String> body = {};
|
||||
body["uid"] = user.id??"";
|
||||
body["token"] = user.token??"";
|
||||
body["job_id"] = request.id ?? '';
|
||||
body["start_time"] = ((timer.startAt?.millisecondsSinceEpoch ?? 0) / 1000)
|
||||
.toStringAsFixed(0);
|
||||
body["end_time"] =
|
||||
((timer.endAt?.millisecondsSinceEpoch ?? 0) / 1000).toStringAsFixed(0);
|
||||
body["working_hours"] =
|
||||
((timer.durationInSecond ?? 0) / 60 / 60).toStringAsFixed(5);
|
||||
body["report_id"] = request.reportID ?? '';
|
||||
try {
|
||||
response = await post(
|
||||
Uri.parse(host + URLs.updateServiceReport),
|
||||
body: body,
|
||||
);
|
||||
//stateCode = response.statusCode;
|
||||
|
||||
if (response.statusCode >= 200 && response.statusCode < 300) {
|
||||
// reset();
|
||||
// notifyListeners();
|
||||
}
|
||||
return response.statusCode;
|
||||
} catch (error) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
Future<ServiceReport> getSingleServiceReport({
|
||||
required String reportId,
|
||||
required String host,
|
||||
required User user,
|
||||
required Subtitle subtitle,
|
||||
}) async {
|
||||
String userData = '';
|
||||
userData += "&uid=${user.id}";
|
||||
userData += "&token=${user.token}";
|
||||
|
||||
Response response;
|
||||
try {
|
||||
response = await get(Uri.parse(
|
||||
'$host${URLs.getServiceReport}?report_id=$reportId$userData',
|
||||
));
|
||||
} catch (error) {
|
||||
throw (HttpStatusManger.getStatusMessage(
|
||||
status: -1, subtitle: subtitle) ??
|
||||
'');
|
||||
}
|
||||
|
||||
// If the call to the server was successful, parse the JSON.
|
||||
if (response.statusCode >= 200 && response.statusCode < 300) {
|
||||
// If the call to the server was successful, parse the JSON.
|
||||
return ServiceReport.fromJson(
|
||||
json.decode(utf8.decode(response.bodyBytes)), reportId);
|
||||
} else {
|
||||
throw (HttpStatusManger.getStatusMessage(
|
||||
status: response.statusCode,
|
||||
subtitle: subtitle,
|
||||
) ??
|
||||
'');
|
||||
}
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue