diff --git a/lib/controllers/providers/api/service_requests_provider.dart b/lib/controllers/providers/api/service_requests_provider.dart index 9d7c2640..169aa892 100644 --- a/lib/controllers/providers/api/service_requests_provider.dart +++ b/lib/controllers/providers/api/service_requests_provider.dart @@ -623,7 +623,6 @@ class ServiceRequestsProvider extends ChangeNotifier { return null; } } catch (error) { - print(error); return null; } } diff --git a/lib/models/service_request/service_request.dart b/lib/models/service_request/service_request.dart index 78828a29..98457831 100644 --- a/lib/models/service_request/service_request.dart +++ b/lib/models/service_request/service_request.dart @@ -1,5 +1,6 @@ import 'package:test_sa/controllers/api_routes/urls.dart'; import 'package:test_sa/models/device/device.dart'; +import 'package:test_sa/models/fault_description.dart'; import 'package:test_sa/models/lookup.dart'; class ServiceRequest { @@ -27,8 +28,9 @@ class ServiceRequest { bool viewReport; String engineerMobile; String deviceModel; - String faultDescription; - String workPerformed; + FaultDescription faultDescription; + + //String workPerformed; String visitDate; DateTime nextVisitDate; String jobSheetNumber; @@ -68,7 +70,7 @@ class ServiceRequest { this.jobSheetNumber, this.visitDate, this.nextVisitDate, - this.workPerformed, + //this.workPerformed, this.reportID, this.defectType, this.priority, @@ -116,11 +118,16 @@ class ServiceRequest { viewReport: parsedJson["workOrder"] != null, deviceModel: parsedJson["asset"]["modelDefinition"]["modelName"], engineerMobile: parsedJson["assignedEmployee"] == null ? null : parsedJson["assignedEmployee"]["phone"], - faultDescription: parsedJson["workOrder"] != null ? parsedJson["workOrder"]["faultDescription"] : null, + faultDescription: parsedJson["workOrder"] != null + ? parsedJson["workOrder"]["faultDescription"] != null + ? FaultDescription.fromJson(parsedJson["workOrder"]["faultDescription"]) + : null + : null, + jobSheetNumber: parsedJson["workOrder"] != null ? parsedJson["workOrder"]["jobSheetNumber"] : null, visitDate: DateTime.tryParse(parsedJson["visitDate"] ?? "").toString().split(" ").first, nextVisitDate: DateTime.tryParse(parsedJson["nextVisitDate"] ?? ""), - workPerformed: parsedJson["workOrder"] != null ? parsedJson["workOrder"]["workPerformed"] : null, + //workPerformed: parsedJson["workOrder"] != null ? parsedJson["workOrder"]["workPerformed"] : null, device: Device.fromJson(parsedJson["asset"]), reviewComment: parsedJson["reviewComment"], type: Lookup.fromJson(parsedJson['typeofRequest']), diff --git a/lib/views/pages/user/requests/create_request.dart b/lib/views/pages/user/requests/create_request.dart index 74000354..67633a3e 100644 --- a/lib/views/pages/user/requests/create_request.dart +++ b/lib/views/pages/user/requests/create_request.dart @@ -65,6 +65,8 @@ class CreateRequestPageState extends State { TextEditingController _maintenanceController, _commentController, _reviewCommentController; DateTime _dateTime; + bool isFirstActionSubmitted = false; + @override void initState() { _maintenanceController = TextEditingController(); @@ -80,28 +82,29 @@ class CreateRequestPageState extends State { } else { _serviceRequest = ServiceRequest(); } - _isLoading = true; + isFirstActionSubmitted = _serviceRequest?.firstAction != null; super.initState(); } - getServiceRequestById(String id) async { - try { - ServiceRequest request = await _serviceRequestsProvider.getServiceRequestObjectById(requestId: id) ?? ""; - _serviceRequest = request; - _device = _serviceRequest.device; - _deviceImages.addAll(_serviceRequest.devicePhotos.map((e) { - return File(e); - }).toList()); - _showDatePicker = _serviceRequest.firstAction != null && _serviceRequest.firstAction.name == "Need a visit"; - if (_showDatePicker && _serviceRequest.visitDate != null) { - _dateTime = DateTime.tryParse(_serviceRequest.visitDate); - } - _isLoading = false; - } catch (ex) { - _isLoading = false; - } - setState(() {}); - } + // + // getServiceRequestById(String id) async { + // try { + // ServiceRequest request = await _serviceRequestsProvider.getServiceRequestObjectById(requestId: id) ?? ""; + // _serviceRequest = request; + // _device = _serviceRequest.device; + // _deviceImages.addAll(_serviceRequest.devicePhotos.map((e) { + // return File(e); + // }).toList()); + // _showDatePicker = _serviceRequest.firstAction != null && _serviceRequest.firstAction.name == "Need a visit"; + // if (_showDatePicker && _serviceRequest.visitDate != null) { + // _dateTime = DateTime.tryParse(_serviceRequest.visitDate); + // } + // _isLoading = false; + // } catch (ex) { + // _isLoading = false; + // } + // setState(() {}); + // } @override void dispose() { @@ -121,10 +124,7 @@ class CreateRequestPageState extends State { _userProvider = Provider.of(context); _settingProvider = Provider.of(context); _subtitle = AppLocalization.of(context).subtitle; - if (_serviceRequestsProvider == null) { - _serviceRequestsProvider = Provider.of(context); - getServiceRequestById(widget.serviceRequest.id); - } + _serviceRequestsProvider = Provider.of(context); return Scaffold( key: _scaffoldKey, @@ -277,6 +277,7 @@ class CreateRequestPageState extends State { if (widget.serviceRequest != null) ServiceRequestedFirstAction( initialValue: _serviceRequest.firstAction, + enabled: !isFirstActionSubmitted, onSelect: (status) { _dateTime = null; _serviceRequest.firstAction = status; @@ -288,6 +289,7 @@ class CreateRequestPageState extends State { if (_showDatePicker) ADatePicker( date: _dateTime, + enable: !isFirstActionSubmitted, from: DateTime.now(), onDatePicker: (date) { _dateTime = date; @@ -400,7 +402,7 @@ class CreateRequestPageState extends State { _serviceRequest.requestedThrough = Provider.of(context, listen: false).getDefaultItem(); _isLoading = true; setState(() {}); - _serviceRequest.devicePhotos = _deviceImages.map((e) => "${e.path.split("/").last}|${base64Encode(e.readAsBytesSync())}").toList(); + _serviceRequest.devicePhotos = _deviceImages.map((e) => _isLocalUrl(e.path) ? "${e.path.split("/").last}|${base64Encode(e.readAsBytesSync())}" : e.path).toList(); if (_serviceRequest.audio != null) { if (_isLocalUrl(_serviceRequest.audio)) { final File file = File(_serviceRequest.audio); diff --git a/lib/views/pages/user/requests/request_details.dart b/lib/views/pages/user/requests/request_details.dart index a794e5f5..de049dca 100644 --- a/lib/views/pages/user/requests/request_details.dart +++ b/lib/views/pages/user/requests/request_details.dart @@ -6,6 +6,7 @@ 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/extensions/int_extensions.dart'; +import 'package:test_sa/extensions/widget_extensions.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'; @@ -16,7 +17,9 @@ import 'package:test_sa/views/pages/user/requests/report/create_service_report.d import 'package:test_sa/views/widgets/buttons/app_back_button.dart'; import 'package:test_sa/views/widgets/buttons/app_button.dart'; import 'package:test_sa/views/widgets/buttons/app_icon_button.dart'; +import 'package:test_sa/views/widgets/images/files_list.dart'; import 'package:test_sa/views/widgets/images/images_list.dart'; +import 'package:test_sa/views/widgets/loaders/app_loading.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'; @@ -28,9 +31,9 @@ import 'report/future_service_report.dart'; class RequestDetailsPage extends StatelessWidget { static const String id = "/call-details"; - final ServiceRequest serviceRequest; + ServiceRequest serviceRequest; - const RequestDetailsPage({Key key, this.serviceRequest}) : super(key: key); + RequestDetailsPage({Key key, this.serviceRequest}) : super(key: key); @override Widget build(BuildContext context) { @@ -39,404 +42,423 @@ class RequestDetailsPage extends StatelessWidget { SettingProvider _settingProvider = Provider.of(context); List workOrders = []; ServiceRequestsProvider _serviceRequestsProvider = Provider.of(context); + _serviceRequestsProvider.getServiceRequestObjectById(requestId: serviceRequest.id); + return DefaultTabController( length: 2, child: Scaffold( body: SafeArea( - child: Column( - children: [ - Container( - color: AColors.primaryColor, - padding: const EdgeInsets.symmetric(horizontal: 0, vertical: 4), - child: Row( - children: [ - ABackButton(), - Expanded( - child: Center( - child: Text( - _subtitle.details, - style: Theme.of(context).textTheme.headline6.copyWith(color: AColors.white, fontStyle: FontStyle.italic), - ), - ), - ), - _userProvider.user.type == UsersTypes.normal_user - ? - // AIconButton( - // iconData: Icons.warning_amber_rounded, - // color: AColors.white, - // buttonSize: 42, - // backgroundColor: AColors.deepOrange, - // onPressed: (){ - // Navigator.of(context).push( - // MaterialPageRoute( - // builder: (_) => ReportIssuesPage(serviceRequest: serviceRequest,) - // ) - // ); - // }, - // ) - const SizedBox( - width: 48, - ) - : AIconButton( - iconData: Icons.edit, - color: AColors.white, - buttonSize: 42, - backgroundColor: AColors.green, - onPressed: () async { - Navigator.of(context).push( - MaterialPageRoute(builder: (_) => CreateRequestPage(serviceRequest: serviceRequest)), - ); - // showModalBottomSheet( - // context: context, - // builder: (context) { - // return ServiceRequestsUpdateDialog( - // request: serviceRequest, - // ); - // }); - // DateTime picked = await showDatePicker( - // context: context, - // initialDate: DateTime.now(), - // firstDate: DateTime.now(), - // lastDate: DateTime.now().add(Duration(days: 182)) - // ); - // if(picked == null){return;} - // showDialog( - // 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: serviceRequest, - // newDate: picked.toString().split(" ").first - // ); - // Navigator.of(context).pop(); - // Fluttertoast.showToast( - // msg: HttpStatusManger.getStatusMessage(status: status, subtitle: _subtitle), - // ); - }, - ), - SizedBox( - width: 16, - ) - ], - ), - ), - serviceRequest.devicePhotos.isEmpty - ? SizedBox.shrink() - : Column( - children: [ - SizedBox( - height: 8, - ), - MaterialButton( - padding: EdgeInsets.zero, - onPressed: () { - Navigator.of(context).push(MaterialPageRoute( - builder: (_) => Scaffold( - body: InteractiveViewer( - child: Center( - child: ImageLoader( - url: serviceRequest.devicePhotos.first, - boxFit: BoxFit.contain, - ), - ), - ), - ))); - }, - child: SizedBox( - height: 140 * AppStyle.getScaleFactor(context), - width: MediaQuery.of(context).size.width, - child: ImageLoader( - url: serviceRequest.devicePhotos.first, - boxFit: BoxFit.cover, - ), - ), - ), - SizedBox(height: 8), - SizedBox( - height: 60 * AppStyle.getScaleFactor(context), - child: ImagesList( - images: serviceRequest.devicePhotos, - ), - ), - ], - ), - TabBar(labelColor: AColors.primaryColor, tabs: [ - Tab( - text: _subtitle.general, - ), - Tab( - text: _subtitle.serviceRequestInformation, - ), - ]), - SizedBox( - height: 8, - ), - Expanded( - child: TabBarView( - children: [ - ListView( - padding: EdgeInsets.symmetric(horizontal: 16), - children: [ - RequestInfoRow( - title: _subtitle.callId, - info: serviceRequest.requestCode, - ), - RequestInfoRow( - title: "Asset Number", - info: serviceRequest.deviceNumber, - ), - RequestInfoRow( - title: _subtitle.assetName, - info: serviceRequest.deviceEnName, - ), - RequestInfoRow( - title: _subtitle.deviceModel, - info: serviceRequest.deviceModel, - ), - RequestInfoRow( - title: _subtitle.engineerName, - info: serviceRequest.engineerName, - ), - RequestInfoRow( - title: _subtitle.engineerPhone, - info: serviceRequest.engineerMobile, - ), - RequestInfoRow( - title: _subtitle.date, - info: serviceRequest.date, - ), - serviceRequest.nextVisitDate == null - ? SizedBox.shrink() - : RequestInfoRow( - title: _subtitle.nextVisitDate, - info: DateFormat('EE dd/MM/yyyy').format(serviceRequest.nextVisitDate), - ), - Row( + child: FutureBuilder( + future: _serviceRequestsProvider.getServiceRequestObjectById(requestId: serviceRequest.id), + builder: (context, snap) { + if (snap.connectionState == ConnectionState.waiting) { + return const ALoading(); + } else if (snap.hasData) { + serviceRequest = snap.data; + return Column( + children: [ + Container( + color: AColors.primaryColor, + padding: const EdgeInsets.symmetric(horizontal: 0, vertical: 4), + child: Row( children: [ + ABackButton(), Expanded( - child: Text( - "${_subtitle.status} : ", - style: Theme.of(context).textTheme.subtitle1, - textScaleFactor: AppStyle.getScaleFactor(context), + child: Center( + child: Text( + _subtitle.details, + style: Theme.of(context).textTheme.headline6.copyWith(color: AColors.white, fontStyle: FontStyle.italic), + ), ), ), - StatusLabel(label: serviceRequest.statusLabel, color: AColors.getRequestStatusColor(serviceRequest.statusValue)), + _userProvider.user.type == UsersTypes.normal_user + ? + // AIconButton( + // iconData: Icons.warning_amber_rounded, + // color: AColors.white, + // buttonSize: 42, + // backgroundColor: AColors.deepOrange, + // onPressed: (){ + // Navigator.of(context).push( + // MaterialPageRoute( + // builder: (_) => ReportIssuesPage(serviceRequest: serviceRequest,) + // ) + // ); + // }, + // ) + const SizedBox( + width: 48, + ) + : AIconButton( + iconData: Icons.edit, + color: AColors.white, + buttonSize: 42, + backgroundColor: AColors.green, + onPressed: () async { + Navigator.of(context).push( + MaterialPageRoute(builder: (_) => CreateRequestPage(serviceRequest: serviceRequest)), + ); + // showModalBottomSheet( + // context: context, + // builder: (context) { + // return ServiceRequestsUpdateDialog( + // request: serviceRequest, + // ); + // }); + // DateTime picked = await showDatePicker( + // context: context, + // initialDate: DateTime.now(), + // firstDate: DateTime.now(), + // lastDate: DateTime.now().add(Duration(days: 182)) + // ); + // if(picked == null){return;} + // showDialog( + // 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: serviceRequest, + // newDate: picked.toString().split(" ").first + // ); + // Navigator.of(context).pop(); + // Fluttertoast.showToast( + // msg: HttpStatusManger.getStatusMessage(status: status, subtitle: _subtitle), + // ); + }, + ), + SizedBox( + width: 16, + ) ], ), - Divider( - color: Theme.of(context).primaryColor, - ), - RequestInfoRow( - title: _subtitle.hospital, - info: serviceRequest.hospitalName, - ), - RequestInfoRow( - title: _subtitle.unite, - info: serviceRequest.departmentName, + ), + serviceRequest.devicePhotos.isEmpty + ? const SizedBox.shrink() + : SizedBox( + height: 60 * AppStyle.getScaleFactor(context), + child: FilesList( + images: serviceRequest.devicePhotos, + ), + ).paddingOnly(top: 4, bottom: 4), + + // Column( + // children: [ + // SizedBox( + // height: 8, + // ), + // MaterialButton( + // padding: EdgeInsets.zero, + // onPressed: () { + // Navigator.of(context).push(MaterialPageRoute( + // builder: (_) => Scaffold( + // body: InteractiveViewer( + // child: Center( + // child: ImageLoader( + // url: serviceRequest.devicePhotos.first, + // boxFit: BoxFit.contain, + // ), + // ), + // ), + // ))); + // }, + // child: SizedBox( + // height: 140 * AppStyle.getScaleFactor(context), + // width: MediaQuery.of(context).size.width, + // child: ImageLoader( + // url: serviceRequest.devicePhotos.first, + // boxFit: BoxFit.cover, + // ), + // ), + // ), + // SizedBox(height: 8), + // SizedBox( + // height: 60 * AppStyle.getScaleFactor(context), + // child: FilesList( + // images: serviceRequest.devicePhotos, + // ), + // ), + // ], + // ), + TabBar(labelColor: AColors.primaryColor, tabs: [ + Tab( + text: _subtitle.general, ), - // RequestInfoRow( - // title: _subtitle.deviceArName, - // content: serviceRequest.deviceArName, - // ), - // RequestInfoRow( - // title: _subtitle.deviceName, - // content: serviceRequest.deviceEnName, - // ), - RequestInfoRow( - title: _subtitle.maintenanceIssue, - content: serviceRequest.callComments, + Tab( + text: _subtitle.serviceRequestInformation, ), - if (serviceRequest.audio?.isNotEmpty == true) - ASoundPlayer( - audio: serviceRequest.audio, - ), - // - // Center( - // child: Padding( - // padding: EdgeInsets.all(32), - // child: AButton( - // text: _subtitle.duplicateRequest, - // onPressed: () async { - // bool result = await showDialog( - // context: context, - // builder: (_) => AAlertDialog( - // title: _subtitle.duplicateAlert, - // content: _subtitle.duplicateAlertMessage, - // ) - // ); - // if(result == true){ - // showDialog( - // context: context, - // builder: (context){ - // return Center(child: CircularProgressIndicator()); - // } - // ); - // int status = await _serviceRequestsProvider.createDuplicatedReport( - // host: _settingProvider.host, - // user: _userProvider.user, - // request: serviceRequest - // ); - // Navigator.of(context).pop(); - // ScaffoldMessenger.of(context).showSnackBar( - // SnackBar( - // content: Text( - // HttpStatusManger.getStatusMessage(status: status, subtitle: _subtitle) - // ) - // ) - // ); - // } - // }, - // ), - // ), - // ) - ], - ), - // workOrders.isEmpty ? - FutureBuilder( - future: _serviceRequestsProvider.searchWorkOrders(callId: serviceRequest.requestCode), - builder: (context, snap) { - workOrders = snap.data as List; - if (snap.connectionState == ConnectionState.waiting) return Center(child: CircularProgressIndicator()); - if (snap.connectionState == ConnectionState.done && (snap.data?.length ?? 0) != 0) { - return SingleChildScrollView( - child: Column( + ]), + SizedBox( + height: 8, + ), + Expanded( + child: TabBarView( + children: [ + ListView( + padding: EdgeInsets.symmetric(horizontal: 16), children: [ - ListView.separated( - shrinkWrap: true, - physics: const NeverScrollableScrollPhysics(), - padding: EdgeInsets.all(21), - itemCount: workOrders.length, - separatorBuilder: (czt, index) => 21.height, - itemBuilder: (context, index) { - 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 ElevatedButton( - style: ElevatedButton.styleFrom( - padding: EdgeInsets.symmetric(vertical: 8, horizontal: 8), - primary: itemColor.withOpacity(.7), - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(AppStyle.getBorderRadius(context)), - ), - ), - //padding: EdgeInsets.symmetric(vertical: 8,horizontal: 8), - onPressed: () { - // onPressed(request); - }, - child: Column( - children: [ - RequestInfoRow( - title: _subtitle.callId, - content: serviceRequest.requestCode, - ), - RequestInfoRow( - title: _subtitle.orderWorkNumber, - info: workOrders[index].workOrderNo.toString(), - ), - RequestInfoRow( - title: _subtitle.visitDate, - info: workOrders[index].visitDate, - ), - RequestInfoRow(title: _subtitle.assignedEmployee, info: workOrders[index].assignedEmployee?.name ?? ""), - RequestInfoRow( - title: _subtitle.assetSN, - info: workOrders[index].callRequest.asset.assetSerialNo, - ), - RequestInfoRow( - title: _subtitle.assetName, - info: workOrders[index].callRequest.asset.modelDefinition.assetName, - ), - RequestInfoRow( - title: _subtitle.assetNumber, - info: workOrders[index].callRequest.asset.assetNumber, - ), - RequestInfoRow( - title: _subtitle.model, - info: workOrders[index].callRequest.asset.modelDefinition.modelName, - ), - RequestInfoRow( - title: _subtitle.site, - info: workOrders[index].callRequest.asset.site.custName, - ), - RequestInfoRow( - title: "Call last Situation", - info: workOrders[index].currentSituation.name ?? '', - ), - _userProvider.user.type == UsersTypes.engineer && workOrders[index].workOrderNo != null - ? Padding( - padding: EdgeInsets.all(32), - child: AButton( - text: _subtitle.editServiceReport, - onPressed: () { - Navigator.of(context).push( - MaterialPageRoute( - builder: (_) => FutureServiceReport( - request: serviceRequest, - workOrder: workOrders[index], - )), - ); - }, - ), - ) - : SizedBox.shrink(), - ], - ), - ); - }, + RequestInfoRow( + title: _subtitle.callId, + info: serviceRequest.requestCode, + ), + RequestInfoRow( + title: "Asset Number", + info: serviceRequest.deviceNumber, + ), + RequestInfoRow( + title: _subtitle.assetName, + info: serviceRequest.deviceEnName, + ), + RequestInfoRow( + title: _subtitle.deviceModel, + info: serviceRequest.deviceModel, ), - if (_userProvider.user.type == UsersTypes.engineer) - Center( - child: Padding( - padding: const EdgeInsets.all(32), - child: AButton( - text: "Create Work Order", - onPressed: () { - Navigator.of(context).push(MaterialPageRoute(builder: (_) => CreateServiceReport(request: serviceRequest))); - }, + RequestInfoRow( + title: _subtitle.engineerName, + info: serviceRequest.engineerName, + ), + RequestInfoRow( + title: _subtitle.engineerPhone, + info: serviceRequest.engineerMobile, + ), + RequestInfoRow( + title: _subtitle.date, + info: serviceRequest.date, + ), + serviceRequest.nextVisitDate == null + ? SizedBox.shrink() + : RequestInfoRow( + title: _subtitle.nextVisitDate, + info: DateFormat('EE dd/MM/yyyy').format(serviceRequest.nextVisitDate), + ), + Row( + children: [ + Expanded( + child: Text( + "${_subtitle.status} : ", + style: Theme.of(context).textTheme.subtitle1, + textScaleFactor: AppStyle.getScaleFactor(context), ), ), + StatusLabel(label: serviceRequest.statusLabel, color: AColors.getRequestStatusColor(serviceRequest.statusValue)), + ], + ), + Divider( + color: Theme.of(context).primaryColor, + ), + RequestInfoRow( + title: _subtitle.hospital, + info: serviceRequest.hospitalName, + ), + RequestInfoRow( + title: _subtitle.unite, + info: serviceRequest.departmentName, + ), + // RequestInfoRow( + // title: _subtitle.deviceArName, + // content: serviceRequest.deviceArName, + // ), + // RequestInfoRow( + // title: _subtitle.deviceName, + // content: serviceRequest.deviceEnName, + // ), + RequestInfoRow( + title: _subtitle.maintenanceIssue, + content: serviceRequest.callComments, + ), + if (serviceRequest.audio?.isNotEmpty == true) + ASoundPlayer( + audio: serviceRequest.audio, ), + // + // Center( + // child: Padding( + // padding: EdgeInsets.all(32), + // child: AButton( + // text: _subtitle.duplicateRequest, + // onPressed: () async { + // bool result = await showDialog( + // context: context, + // builder: (_) => AAlertDialog( + // title: _subtitle.duplicateAlert, + // content: _subtitle.duplicateAlertMessage, + // ) + // ); + // if(result == true){ + // showDialog( + // context: context, + // builder: (context){ + // return Center(child: CircularProgressIndicator()); + // } + // ); + // int status = await _serviceRequestsProvider.createDuplicatedReport( + // host: _settingProvider.host, + // user: _userProvider.user, + // request: serviceRequest + // ); + // Navigator.of(context).pop(); + // ScaffoldMessenger.of(context).showSnackBar( + // SnackBar( + // content: Text( + // HttpStatusManger.getStatusMessage(status: status, subtitle: _subtitle) + // ) + // ) + // ); + // } + // }, + // ), + // ), + // ) ], ), - ); - } else { - return Column( - children: [ - Expanded( - child: Center( - child: ASubTitle(_subtitle.dataNotFound), - ), - ), - if (_userProvider.user.type == UsersTypes.engineer) - Center( - child: Padding( - padding: const EdgeInsets.all(32), - child: AButton( - text: "Create Work Order", - onPressed: () { - Navigator.of(context).push(MaterialPageRoute(builder: (_) => CreateServiceReport(request: serviceRequest))); - }, + // workOrders.isEmpty ? + FutureBuilder( + future: _serviceRequestsProvider.searchWorkOrders(callId: serviceRequest.requestCode), + builder: (context, snap) { + workOrders = snap.data as List; + if (snap.connectionState == ConnectionState.waiting) return Center(child: CircularProgressIndicator()); + if (snap.connectionState == ConnectionState.done && (snap.data?.length ?? 0) != 0) { + return SingleChildScrollView( + child: Column( + children: [ + ListView.separated( + shrinkWrap: true, + physics: const NeverScrollableScrollPhysics(), + padding: EdgeInsets.all(21), + itemCount: workOrders.length, + separatorBuilder: (czt, index) => 21.height, + itemBuilder: (context, index) { + 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 ElevatedButton( + style: ElevatedButton.styleFrom( + padding: EdgeInsets.symmetric(vertical: 8, horizontal: 8), + primary: itemColor.withOpacity(.7), + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(AppStyle.getBorderRadius(context)), + ), + ), + //padding: EdgeInsets.symmetric(vertical: 8,horizontal: 8), + onPressed: () { + // onPressed(request); + }, + child: Column( + children: [ + RequestInfoRow( + title: _subtitle.callId, + content: serviceRequest.requestCode, + ), + RequestInfoRow( + title: _subtitle.orderWorkNumber, + info: workOrders[index].workOrderNo.toString(), + ), + RequestInfoRow( + title: _subtitle.visitDate, + info: workOrders[index].visitDate, + ), + RequestInfoRow(title: _subtitle.assignedEmployee, info: workOrders[index].assignedEmployee?.name ?? ""), + RequestInfoRow( + title: _subtitle.assetSN, + info: workOrders[index].callRequest.asset.assetSerialNo, + ), + RequestInfoRow( + title: _subtitle.assetName, + info: workOrders[index].callRequest.asset.modelDefinition.assetName, + ), + RequestInfoRow( + title: _subtitle.assetNumber, + info: workOrders[index].callRequest.asset.assetNumber, + ), + RequestInfoRow( + title: _subtitle.model, + info: workOrders[index].callRequest.asset.modelDefinition.modelName, + ), + RequestInfoRow( + title: _subtitle.site, + info: workOrders[index].callRequest.asset.site.custName, + ), + RequestInfoRow( + title: "Call last Situation", + info: workOrders[index].currentSituation.name ?? '', + ), + _userProvider.user.type == UsersTypes.engineer && workOrders[index].workOrderNo != null + ? Padding( + padding: EdgeInsets.all(32), + child: AButton( + text: _subtitle.editServiceReport, + onPressed: () { + Navigator.of(context).push( + MaterialPageRoute( + builder: (_) => FutureServiceReport( + request: serviceRequest, + workOrder: workOrders[index], + )), + ); + }, + ), + ) + : SizedBox.shrink(), + ], + ), + ); + }, + ), + if (_userProvider.user.type == UsersTypes.engineer) + Center( + child: Padding( + padding: const EdgeInsets.all(32), + child: AButton( + text: "Create Work Order", + onPressed: () { + Navigator.of(context).push(MaterialPageRoute(builder: (_) => CreateServiceReport(request: serviceRequest))); + }, + ), + ), + ), + ], ), - ), - ), - ], - ); - } - }, - ), - ], - ), - ), - ], - ), + ); + } else { + return Column( + children: [ + Expanded( + child: Center( + child: ASubTitle(_subtitle.dataNotFound), + ), + ), + if (_userProvider.user.type == UsersTypes.engineer) + Center( + child: Padding( + padding: const EdgeInsets.all(32), + child: AButton( + text: "Create Work Order", + onPressed: () { + Navigator.of(context).push(MaterialPageRoute(builder: (_) => CreateServiceReport(request: serviceRequest))); + }, + ), + ), + ), + ], + ); + } + }, + ), + ], + ), + ), + ], + ); + } + return const SizedBox(); + }), ), ), ); diff --git a/lib/views/widgets/date_and_time/date_picker.dart b/lib/views/widgets/date_and_time/date_picker.dart index 54c4ef8c..09f66465 100644 --- a/lib/views/widgets/date_and_time/date_picker.dart +++ b/lib/views/widgets/date_and_time/date_picker.dart @@ -6,8 +6,9 @@ class ADatePicker extends StatelessWidget { final DateTime from; final DateTime to; final Function(DateTime) onDatePicker; + final bool enable; - const ADatePicker({Key key, this.date, this.onDatePicker, this.from, this.to}) : super(key: key); + const ADatePicker({Key key, this.date, this.onDatePicker, this.from, this.to, this.enable = true}) : super(key: key); @override Widget build(BuildContext context) { @@ -19,14 +20,16 @@ class ADatePicker extends StatelessWidget { borderRadius: BorderRadius.circular(12 * AppStyle.getScaleFactor(context)), ), ), + onPressed: enable + ? () async { + DateTime picked = await showDatePicker(context: context, initialDate: DateTime.now(), firstDate: from ?? DateTime.now(), lastDate: to ?? DateTime.now().add(Duration(days: 365))); + onDatePicker(picked); + } + : null, child: Text( date == null ? "Pick Date" : date.toString().split(" ").first, textScaleFactor: AppStyle.getScaleFactor(context), ), - onPressed: () async { - DateTime picked = await showDatePicker(context: context, initialDate: DateTime.now(), firstDate: from ?? DateTime.now(), lastDate: to ?? DateTime.now().add(Duration(days: 365))); - onDatePicker(picked); - }, ); } } diff --git a/lib/views/widgets/images/files_list.dart b/lib/views/widgets/images/files_list.dart new file mode 100644 index 00000000..6cfd8a85 --- /dev/null +++ b/lib/views/widgets/images/files_list.dart @@ -0,0 +1,75 @@ +import 'dart:io'; + +import 'package:flutter/material.dart'; +import 'package:fluttertoast/fluttertoast.dart'; +import 'package:open_file/open_file.dart'; +import 'package:test_sa/extensions/int_extensions.dart'; +import 'package:test_sa/extensions/widget_extensions.dart'; +import 'package:test_sa/views/app_style/sizing.dart'; +import 'package:test_sa/views/widgets/buttons/app_back_button.dart'; +import 'package:test_sa/views/widgets/loaders/image_loader.dart'; +import 'package:url_launcher/url_launcher.dart'; + +import 'image_item.dart'; +import 'images_viewer.dart'; + +class FilesList extends StatelessWidget { + final List images; + final EdgeInsets padding; + + const FilesList({Key key, this.images, this.padding}) : super(key: key); + + @override + Widget build(BuildContext context) { + return ListView.separated( + padding: padding ?? EdgeInsets.symmetric(horizontal: 32 * AppStyle.getScaleFactor(context)), + scrollDirection: Axis.horizontal, + itemCount: images.length, + separatorBuilder: (context, itemIndex) => 8.width, + itemBuilder: (context, itemIndex) { + var isImage = + images[itemIndex].split(".").last.toLowerCase() == "png" || images[itemIndex].split(".").last.toLowerCase() == "jpg" || images[itemIndex].split(".").last.toLowerCase() == "jpeg"; + var isPdf = images[itemIndex].split(".").last.toLowerCase() == "pdf"; + var isExcel = images[itemIndex].split(".").last.toLowerCase() == "xlsx"; + + return (isImage + ? (_isLocalUrl(images[itemIndex]) + ? Image.file(File(images[itemIndex])) + : ImageLoader( + url: images[itemIndex], + boxFit: BoxFit.cover, + )) + : Image.asset("assets/images/${isPdf ? "pdf" : isExcel ? "excel" : "doc"}.png")) + .onPress(() async { + if (isImage) { + Navigator.of(context).push( + MaterialPageRoute( + builder: (_) => Scaffold( + body: SafeArea( + child: Stack( + children: [ + InteractiveViewer(child: Image(image: (_isLocalUrl(images[itemIndex]) ? FileImage(File(images[itemIndex])) : NetworkImage(images[itemIndex])))).center, + const ABackButton(), + ], + ), + ), + ), + ), + ); + } else if (_isLocalUrl(images[itemIndex])) { + OpenFile.open(images[itemIndex]); + } else { + if (!await launchUrl(Uri.parse(images[itemIndex]), mode: LaunchMode.externalApplication)) { + Fluttertoast.showToast(msg: "UnExpected Error with file."); + throw Exception('Could not launch '); + } + } + }); + }); + } + + bool _isLocalUrl(String url) { + if (url?.isEmpty != false) return false; + return url.startsWith("/") || url.startsWith("file://") || url.substring(1).startsWith(':\\'); + } +} diff --git a/lib/views/widgets/images/multi_image_picker_item.dart b/lib/views/widgets/images/multi_image_picker_item.dart index fea9ce6f..d5b00011 100644 --- a/lib/views/widgets/images/multi_image_picker_item.dart +++ b/lib/views/widgets/images/multi_image_picker_item.dart @@ -1,9 +1,14 @@ import 'dart:io'; import 'package:flutter/material.dart'; +import 'package:fluttertoast/fluttertoast.dart'; +import 'package:open_file/open_file.dart'; +import 'package:test_sa/extensions/widget_extensions.dart'; import 'package:test_sa/views/app_style/colors.dart'; import 'package:test_sa/views/app_style/sizing.dart'; import 'package:test_sa/views/widgets/buttons/app_back_button.dart'; +import 'package:test_sa/views/widgets/loaders/image_loader.dart'; +import 'package:url_launcher/url_launcher.dart'; class MultiFilesPickerItem extends StatelessWidget { final File file; @@ -31,7 +36,7 @@ class MultiFilesPickerItem extends StatelessWidget { ), child: MaterialButton( padding: EdgeInsets.zero, - onPressed: () { + onPressed: () async { if (isImage) { Navigator.of(context).push( MaterialPageRoute( @@ -39,7 +44,14 @@ class MultiFilesPickerItem extends StatelessWidget { body: SafeArea( child: Stack( children: [ - Center(child: isImage ? InteractiveViewer(child: Image(image: (_isLocalUrl(file.path) ? FileImage(file) : NetworkImage(file.path)))) : const SizedBox.shrink()), + InteractiveViewer( + child: _isLocalUrl(file.path) + ? Image.file(file) + : ImageLoader( + url: file.path, + boxFit: BoxFit.cover, + )) + .center, const ABackButton(), ], ), @@ -47,6 +59,13 @@ class MultiFilesPickerItem extends StatelessWidget { ), ), ); + } else if (_isLocalUrl(file.path)) { + OpenFile.open(file.path); + } else { + if (!await launchUrl(Uri.parse(file.path), mode: LaunchMode.externalApplication)) { + Fluttertoast.showToast(msg: "UnExpected Error with file."); + throw Exception('Could not launch '); + } } }, child: Align( diff --git a/lib/views/widgets/status/service_request/service_request_first_action.dart b/lib/views/widgets/status/service_request/service_request_first_action.dart index 02c5f94e..99511972 100644 --- a/lib/views/widgets/status/service_request/service_request_first_action.dart +++ b/lib/views/widgets/status/service_request/service_request_first_action.dart @@ -11,8 +11,9 @@ import '../../../../controllers/providers/api/status_drop_down/service_reqest/se class ServiceRequestedFirstAction extends StatelessWidget { final Function(Lookup) onSelect; final Lookup initialValue; + final bool enabled; - const ServiceRequestedFirstAction({Key key, this.onSelect, this.initialValue}) : super(key: key); + const ServiceRequestedFirstAction({Key key, this.onSelect, this.initialValue, this.enabled = true}) : super(key: key); @override Widget build(BuildContext context) { final settingProvider = Provider.of(context); @@ -30,6 +31,7 @@ class ServiceRequestedFirstAction extends StatelessWidget { initialStatus: initialValue, statuses: menuProvider.items, onSelect: onSelect, + enabled: enabled, ), ); } diff --git a/pubspec.lock b/pubspec.lock index 98397238..87291639 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -701,6 +701,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.0.2" + open_file: + dependency: "direct main" + description: + name: open_file + sha256: a5a32d44acb7c899987d0999e1e3cbb0a0f1adebbf41ac813ec6d2d8faa0af20 + url: "https://pub.dev" + source: hosted + version: "3.3.2" package_info: dependency: "direct main" description: diff --git a/pubspec.yaml b/pubspec.yaml index 4616c3d2..677ef09c 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -64,6 +64,7 @@ dependencies: file_picker: ^5.2.5 record_mp3: ^2.1.0 path_provider: ^2.1.0 + open_file: ^3.3.2 dev_dependencies: flutter_test: