diff --git a/lib/controllers/providers/api/service_requests_provider.dart b/lib/controllers/providers/api/service_requests_provider.dart index e3428ed3..6331eec6 100644 --- a/lib/controllers/providers/api/service_requests_provider.dart +++ b/lib/controllers/providers/api/service_requests_provider.dart @@ -233,6 +233,7 @@ class ServiceRequestsProvider extends ChangeNotifier { } Future updateRequest({ + @required BuildContext context, @required User user, @required ServiceRequest request, }) async { diff --git a/lib/views/pages/user/requests/create_service_request_page.dart b/lib/views/pages/user/requests/create_service_request_page.dart index c04d69d3..56d92c41 100644 --- a/lib/views/pages/user/requests/create_service_request_page.dart +++ b/lib/views/pages/user/requests/create_service_request_page.dart @@ -186,6 +186,10 @@ class CreateServiceRequestPageState extends State { controller: _commentController, labelText: context.translation.comments, suffixIcon: "warning".toSvgAsset(color: context.isDark ? AppColor.neutral10 : AppColor.neutral20, width: 24).paddingOnly(end: 16), + initialValue: _serviceRequest.callComments, + onSaved: (text) { + _serviceRequest.callComments = text; + }, ), 8.height, RecordSound( diff --git a/lib/views/pages/user/requests/first_action_bottom_sheet.dart b/lib/views/pages/user/requests/first_action_bottom_sheet.dart index fcccef91..af0d539c 100644 --- a/lib/views/pages/user/requests/first_action_bottom_sheet.dart +++ b/lib/views/pages/user/requests/first_action_bottom_sheet.dart @@ -108,7 +108,7 @@ class _FirstActionBottomSheetState extends State { loading: snapshot.isLoading, onPressed: () async { _formKey.currentState.save(); - await snapshot.updateRequest(user: userProvider.user, request: _serviceRequest); + await snapshot.updateRequest(context: context, user: userProvider.user, request: _serviceRequest); Navigator.pop(context); }, ), diff --git a/lib/views/pages/user/requests/service_request_details.dart b/lib/views/pages/user/requests/service_request_details.dart index 20bdb790..0ce5b97c 100644 --- a/lib/views/pages/user/requests/service_request_details.dart +++ b/lib/views/pages/user/requests/service_request_details.dart @@ -93,9 +93,9 @@ class ServiceRequestDetailsPage extends StatelessWidget { Column( crossAxisAlignment: CrossAxisAlignment.end, children: [ - if (_userProvider.user.type == UsersTypes.engineer) + if (_userProvider.user.type == UsersTypes.normal_user) "edit".toSvgAsset(width: 48).onPress(() { - Navigator.push(context, MaterialPageRoute(builder: (context) => const UpdateServiceRequestPage())); + Navigator.push(context, MaterialPageRoute(builder: (context) => UpdateServiceRequestPage(serviceRequest: serviceRequest))); }), if (_userProvider.user.type == UsersTypes.engineer) 16.height, Text(serviceRequest.date.toServiceRequestCardFormat, textAlign: TextAlign.end, style: AppTextStyles.tinyFont.copyWith(color: const Color(0xFF3B3D4A))), diff --git a/lib/views/pages/user/requests/update_service_request_page.dart b/lib/views/pages/user/requests/update_service_request_page.dart index 1e4b0cc3..d7fe80b5 100644 --- a/lib/views/pages/user/requests/update_service_request_page.dart +++ b/lib/views/pages/user/requests/update_service_request_page.dart @@ -1,20 +1,173 @@ +import 'dart:convert'; +import 'dart:io'; + import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; +import 'package:test_sa/controllers/providers/api/service_requests_provider.dart'; +import 'package:test_sa/controllers/providers/api/user_provider.dart'; import 'package:test_sa/extensions/context_extension.dart'; +import 'package:test_sa/extensions/int_extensions.dart'; +import 'package:test_sa/extensions/text_extensions.dart'; +import 'package:test_sa/extensions/widget_extensions.dart'; +import 'package:test_sa/models/service_request/service_request.dart'; import 'package:test_sa/new_views/common_widgets/default_app_bar.dart'; -class UpdateServiceRequestPage extends StatelessWidget { +import '../../../../models/lookup.dart'; +import '../../../../new_views/app_style/app_color.dart'; +import '../../../../new_views/common_widgets/app_filled_button.dart'; +import '../../../../new_views/common_widgets/app_text_form_field.dart'; +import '../../../../new_views/common_widgets/single_item_drop_down_menu.dart'; +import '../../../../providers/service_request_providers/equipment_status_provider.dart'; +import '../../../../providers/service_request_providers/priority_provider.dart'; +import '../../../../providers/service_request_providers/requested_through_provider.dart'; +import '../../../../providers/service_request_providers/type_of_request_provider.dart'; +import '../../../widgets/equipment/pick_asset.dart'; +import '../../../widgets/images/multi_image_picker.dart'; +import '../../../widgets/sound/record_sound.dart'; + +class UpdateServiceRequestPage extends StatefulWidget { static const String id = "/update_service_request_page"; - const UpdateServiceRequestPage({Key key}) : super(key: key); + final ServiceRequest serviceRequest; + const UpdateServiceRequestPage({Key key, this.serviceRequest}) : super(key: key); + + @override + State createState() => _UpdateServiceRequestPageState(); +} + +class _UpdateServiceRequestPageState extends State { + final GlobalKey _formKey = GlobalKey(); + TextEditingController _commentController; + List _deviceImages = []; + UserProvider _userProvider; + + @override + void initState() { + super.initState(); + _deviceImages = widget.serviceRequest.devicePhotos.map((e) => File(e)).toList(); + _commentController = TextEditingController(text: widget.serviceRequest.callComments ?? ""); + } + + @override + void dispose() { + _commentController.dispose(); + super.dispose(); + } @override Widget build(BuildContext context) { + _userProvider = Provider.of(context, listen: false); return Scaffold( appBar: DefaultAppBar(title: context.translation.updateServiceRequest), body: SafeArea( - child: Column( - children: [], - ), + child: Form( + key: _formKey, + child: Column( + children: [ + SingleChildScrollView( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + PickAsset( + editable: false, + device: widget.serviceRequest.device, + onPickAsset: (asset) { + widget.serviceRequest.device = asset; + setState(() {}); + }, + ), + 8.height, + SingleItemDropDownMenu( + context: context, + title: context.translation.priority, + initialValue: widget.serviceRequest?.priority, + onSelect: (value) { + widget.serviceRequest.priority = value; + }, + ), + 8.height, + SingleItemDropDownMenu( + context: context, + title: context.translation.equipmentStatus, + initialValue: widget.serviceRequest?.defectType, + onSelect: (value) { + widget.serviceRequest.defectType = value; + }, + ), + 8.height, + Consumer(builder: (context, snapshot, _) { + return SingleItemDropDownMenu( + context: context, + enabled: false, + title: context.translation.requestedThrough, + initialValue: snapshot.items?.firstWhere((element) => element.value == 3, orElse: () => null), + ); + }), + 8.height, + SingleItemDropDownMenu( + context: context, + title: context.translation.typeOfRequest, + initialValue: widget.serviceRequest?.type, + onSelect: (value) { + widget.serviceRequest.type = value; + }, + ), + 8.height, + MultiFilesPicker( + label: context.translation.attachImage, + onlyImages: true, + files: _deviceImages, + ), + ((widget.serviceRequest.devicePhotos?.isNotEmpty ?? false) ? 16 : 8).height, + Align( + alignment: AlignmentDirectional.centerStart, + child: context.translation.callComments.heading5(context), + ), + 8.height, + AppTextFormField( + controller: _commentController, + labelText: context.translation.comments, + initialValue: widget.serviceRequest.callComments, + suffixIcon: "warning".toSvgAsset(color: context.isDark ? AppColor.neutral10 : AppColor.neutral20, width: 24).paddingOnly(end: 16), + onSaved: (text) { + widget.serviceRequest.callComments = text; + }, + ), + 8.height, + RecordSound( + onRecord: (audio) { + widget.serviceRequest.audio = audio; + }, + enabled: widget.serviceRequest == null ? true : false, + ), + 16.height, + ], + ), + ).expanded, + AppFilledButton(onPressed: _submit, label: context.translation.submitRequest), + ], + ), + ).paddingOnly(start: 16, end: 16, bottom: 24, top: 16), ), ); } + + Future _submit() async { + widget.serviceRequest?.requestedThrough = Provider.of(context, listen: false).items?.firstWhere((element) => element.value == 3, orElse: () => null); + if (_formKey.currentState.validate() && await widget.serviceRequest.validateNewRequest(context)) { + _formKey.currentState.save(); + widget.serviceRequest.devicePhotos = _deviceImages.map((e) => _isLocalUrl(e.path) ? "${e.path.split("/").last}|${base64Encode(e.readAsBytesSync())}" : e.path).toList(); + if (widget.serviceRequest.audio != null) { + if (_isLocalUrl(widget.serviceRequest.audio)) { + final File file = File(widget.serviceRequest.audio); + widget.serviceRequest.audio = "${file.path.split("/").last}|${base64Encode(file.readAsBytesSync())}"; + } + } + await Provider.of(context, listen: false).updateRequest(context: context, user: _userProvider.user, request: widget.serviceRequest); + } + } + + 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/equipment/pick_asset.dart b/lib/views/widgets/equipment/pick_asset.dart index e3cddf2b..756deff6 100644 --- a/lib/views/widgets/equipment/pick_asset.dart +++ b/lib/views/widgets/equipment/pick_asset.dart @@ -12,36 +12,38 @@ import '../../../new_views/common_widgets/asset_info_card.dart'; class PickAsset extends StatelessWidget { final Function(Asset) onPickAsset; final Asset device; + final bool editable; - const PickAsset({Key key, this.device, this.onPickAsset}) : super(key: key); + const PickAsset({Key key, this.editable = true, this.device, this.onPickAsset}) : super(key: key); @override Widget build(BuildContext context) { return Column( children: [ - Container( - decoration: BoxDecoration( - color: Theme.of(context).cardColor, - borderRadius: BorderRadius.circular(10), - boxShadow: [BoxShadow(color: Colors.black.withOpacity(0.03), blurRadius: 14)], + if (editable) + Container( + decoration: BoxDecoration( + color: Theme.of(context).cardColor, + borderRadius: BorderRadius.circular(10), + boxShadow: [BoxShadow(color: Colors.black.withOpacity(0.03), blurRadius: 14)], + ), + padding: EdgeInsets.symmetric(horizontal: 16.toScreenWidth, vertical: 8.toScreenHeight), + child: Row( + children: [ + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + context.translation.device.tinyFont(context).custom(color: context.isDark ? AppColor.neutral40 : AppColor.neutral50), + context.translation.pickAsset.bodyText(context).custom(color: context.isDark ? AppColor.neutral40 : AppColor.neutral50), + ], + ).onPress(() async { + Asset device = await Navigator.of(context).pushNamed(SingleDevicePicker.id) as Asset; + onPickAsset(device); + }).expanded, + "qr".toSvgAsset(height: 24, fit: BoxFit.fitHeight, color: context.isDark ? AppColor.primary40 : AppColor.primary70), + ], + ), ), - padding: EdgeInsets.symmetric(horizontal: 16.toScreenWidth, vertical: 8.toScreenHeight), - child: Row( - children: [ - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - context.translation.device.tinyFont(context).custom(color: context.isDark ? AppColor.neutral40 : AppColor.neutral50), - context.translation.pickAsset.bodyText(context).custom(color: context.isDark ? AppColor.neutral40 : AppColor.neutral50), - ], - ).onPress(() async { - Asset device = await Navigator.of(context).pushNamed(SingleDevicePicker.id) as Asset; - onPickAsset(device); - }).expanded, - "qr".toSvgAsset(height: 24, fit: BoxFit.fitHeight, color: context.isDark ? AppColor.primary40 : AppColor.primary70), - ], - ), - ), if (device != null) AssetInfoCard(asset: device).paddingOnly(top: 8), ], );