diff --git a/lib/controllers/providers/api/regular_visits_provider.dart b/lib/controllers/providers/api/regular_visits_provider.dart index 7209c08a..fccfe190 100644 --- a/lib/controllers/providers/api/regular_visits_provider.dart +++ b/lib/controllers/providers/api/regular_visits_provider.dart @@ -1,16 +1,20 @@ import 'dart:convert'; -import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:fluttertoast/fluttertoast.dart'; import 'package:http/http.dart'; import 'package:logger/logger.dart'; import 'package:test_sa/controllers/api_routes/api_manager.dart'; import 'package:test_sa/controllers/api_routes/urls.dart'; +import 'package:test_sa/extensions/context_extension.dart'; import 'package:test_sa/models/pantry/pentry.dart'; import 'package:test_sa/models/user.dart'; import 'package:test_sa/models/visits/visit.dart'; import 'package:test_sa/models/visits/visits_group.dart'; import 'package:test_sa/models/visits/visits_search.dart'; +import '../../../new_views/common_widgets/app_lazy_loading.dart'; + class RegularVisitsProvider extends ChangeNotifier { // number of items call in each request final pageItemNumber = 12; @@ -134,10 +138,9 @@ class RegularVisitsProvider extends ChangeNotifier { } } - Future getPently({String host, User user, int id}) async { + Future getPentry({String host, User user, int id}) async { Response response; - response = await get(Uri.parse("$host${URLs.getPentry}/$id"), headers: {"Content-Type": "application/json; charset=utf-8"}); - + response = await ApiManager.instance.get("${URLs.getPentry}/$id"); Pentry pantry; if (response.statusCode >= 200 && response.statusCode < 300) { pantry = Pentry.fromMap(json.decode(utf8.decode(response.bodyBytes))); @@ -145,13 +148,14 @@ class RegularVisitsProvider extends ChangeNotifier { return pantry; } - Future updatePentry({ - @required String host, + Future updatePentry( + BuildContext context, { @required User user, @required Pentry pentry, @required Visit visit, }) async { try { + showDialog(context: context, barrierDismissible: false, builder: (context) => const AppLazyLoading()); Response response; Map body = pentry.toMap(visit.id); body["id"] = visit.id; @@ -170,7 +174,12 @@ class RegularVisitsProvider extends ChangeNotifier { if (response.statusCode >= 200 && response.statusCode < 300) { reset(); //visit.status = pentry.ppmVisitStatus; notifyListeners(); + Fluttertoast.showToast(msg: context.translation.successfulRequestMessage); + Navigator.of(context).pop(); + } else { + Fluttertoast.showToast(msg: "${context.translation.failedToCompleteRequest} ${jsonDecode(response.body)["message"]}"); } + Navigator.of(context).pop(); return response.statusCode; } catch (error) { return -1; diff --git a/lib/extensions/string_extensions.dart b/lib/extensions/string_extensions.dart index d0e7904f..6c1a9a7d 100644 --- a/lib/extensions/string_extensions.dart +++ b/lib/extensions/string_extensions.dart @@ -7,7 +7,11 @@ extension StringExtensions on String { } String get toServiceRequestDetailsFormat { - DateTime dateTime = DateTime.tryParse(this); - return "${DateFormat('dd MMM, yyyy').format(dateTime)} ${DateFormat('hh:mm a').format(dateTime)}"; + try { + DateTime dateTime = DateTime.tryParse(this); + return "${DateFormat('dd MMM, yyyy').format(dateTime)} ${DateFormat('hh:mm a').format(dateTime)}"; + } catch (e) { + return "null"; + } } } diff --git a/lib/l10n/app_ar.arb b/lib/l10n/app_ar.arb index 68235356..9523a7d9 100644 --- a/lib/l10n/app_ar.arb +++ b/lib/l10n/app_ar.arb @@ -304,5 +304,7 @@ "partNo" : "الجزء رقم", "engSign" : "توقيع المهندس", "requesterName" : "اسم الطالب", - "updateWorkOrder" : "تعديل طلب العمل" + "updateWorkOrder" : "تعديل طلب العمل", + "createPreventiveMaintenanceRequest" : "إنشاء طلب صيانة وقائية", + "createNewRequest" : "إنشاء طلب جديد" } \ No newline at end of file diff --git a/lib/l10n/app_en.arb b/lib/l10n/app_en.arb index de54e1d8..d76461ad 100644 --- a/lib/l10n/app_en.arb +++ b/lib/l10n/app_en.arb @@ -308,6 +308,7 @@ "partNo" : "Part No.", "engSign" : "Engineer Signature", "requesterName" : "Requester Name", - "updateWorkOrder" : "Update Work Order" - + "updateWorkOrder" : "Update Work Order", + "createPreventiveMaintenanceRequest" : "Create Preventive Maintenance Request", + "createNewRequest" : "Create New Request" } \ No newline at end of file diff --git a/lib/main.dart b/lib/main.dart index c19c9bf6..6b3e6cd7 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -53,6 +53,8 @@ import 'package:test_sa/providers/gas_request_providers/gas_status_provider.dart import 'package:test_sa/providers/gas_request_providers/gas_types_provider.dart'; import 'package:test_sa/providers/gas_request_providers/site_provider.dart'; import 'package:test_sa/providers/loading_list_notifier.dart'; +import 'package:test_sa/providers/ppm_device_status_provider.dart'; +import 'package:test_sa/providers/ppm_visit_status_provider.dart'; import 'package:test_sa/providers/service_request_providers/equipment_status_provider.dart'; import 'package:test_sa/providers/service_request_providers/first_action_provider.dart'; import 'package:test_sa/providers/service_request_providers/loan_availability_provider.dart'; @@ -176,6 +178,9 @@ class MyApp extends StatelessWidget { ChangeNotifierProvider(create: (_) => LoanAvailabilityProvider()), ChangeNotifierProvider(create: (_) => ReasonProvider()), ChangeNotifierProvider(create: (_) => ServiceTypeProvider()), + ChangeNotifierProvider(create: (_) => PPMVisitStatusProvider()), + ChangeNotifierProvider(create: (_) => PentryTaskStatusProvider()), + ChangeNotifierProvider(create: (_) => PPMDeviceStatusProvider()), ], child: GestureDetector( onTap: () { diff --git a/lib/models/pantry/pentry.dart b/lib/models/pantry/pentry.dart index c59e651f..85fa0eb4 100644 --- a/lib/models/pantry/pentry.dart +++ b/lib/models/pantry/pentry.dart @@ -48,12 +48,16 @@ class Pentry { this.localEngineerSignature}); Future validate() async { + if (ppmVisitStatus == null) { + await Fluttertoast.showToast(msg: "PPM Visit Status is Required"); + return false; + } if (actualVisitDate == null) { await Fluttertoast.showToast(msg: "Actual visit date is Required"); return false; } if (expectedVisitDate == null) { - await Fluttertoast.showToast(msg: "expected visit date is Required"); + await Fluttertoast.showToast(msg: "Expected visit date is Required"); return false; } if (timer?.startAt == null) { @@ -64,7 +68,6 @@ class Pentry { await Fluttertoast.showToast(msg: "Please Stop The Timer"); return false; } - if (ppmVisitStatus == null) return false; if (status?.id == null) { await Fluttertoast.showToast(msg: "Device Status is Required"); return false; @@ -75,8 +78,8 @@ class Pentry { Map toMap(int visitId) { Map map = {}; - map["visitStatusId"] = ppmVisitStatus?.id?.toString(); - if (status != null) map["deviceStatusId"] = status?.id?.toString(); + map["visitStatusId"] = ppmVisitStatus?.id; + if (status != null) map["deviceStatusId"] = status?.id; if (travelingHours != null) map["travelingHours"] = travelingHours; //if(imageFile != null) map["file_attachement"] = base64Encode(imageFile.readAsBytesSync()); map["actualDate"] = actualVisitDate.toIso8601String(); diff --git a/lib/models/pantry/pm_kit.dart b/lib/models/pantry/pm_kit.dart index fb3fa857..c32d2458 100644 --- a/lib/models/pantry/pm_kit.dart +++ b/lib/models/pantry/pm_kit.dart @@ -16,12 +16,12 @@ class PMKit { return { "id": id ?? 0, "visitId": visitId, - if (itemCode != null) 'partCatalogItemId': (itemCode?.id).toString(), - // if(itemName != null) 'itemName': itemName, + if (itemCode != null) 'partCatalogItemId': (itemCode?.id), + if (itemName != null) 'itemName': itemName, // if(preparationTimeFrame != null) 'preparationTimeFrame': preparationTimeFrame, // if(kitFrequencyDemand != null) 'kitFrequencyDemand': kitFrequencyDemand, // if(availability != null) 'availability': availability, - // if(quantityNeeded != null) 'quantityNeeded': quantityNeeded, + if (quantityNeeded != null) 'quantityNeeded': quantityNeeded, // if(quantityReserved != null) 'quantityReserved': quantityReserved, }; } diff --git a/lib/new_views/common_widgets/app_text_form_field.dart b/lib/new_views/common_widgets/app_text_form_field.dart index 2e1af846..29676754 100644 --- a/lib/new_views/common_widgets/app_text_form_field.dart +++ b/lib/new_views/common_widgets/app_text_form_field.dart @@ -28,31 +28,31 @@ class AppTextFormField extends StatefulWidget { final Color backgroundColor; final bool alignLabelWithHint; - const AppTextFormField({ - 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.prefixIcon, - this.prefixIconData, - this.prefixIconSize, - this.controller, - this.textInputAction, - this.onAction, - this.backgroundColor, - this.alignLabelWithHint - }) : super(key: key); + const AppTextFormField( + {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.prefixIcon, + this.prefixIconData, + this.prefixIconSize, + this.controller, + this.textInputAction, + this.onAction, + this.backgroundColor, + this.alignLabelWithHint}) + : super(key: key); @override State createState() => _AppTextFormFieldState(); diff --git a/lib/providers/pentry_task_status_provider.dart b/lib/providers/pentry_task_status_provider.dart new file mode 100644 index 00000000..aaf7a352 --- /dev/null +++ b/lib/providers/pentry_task_status_provider.dart @@ -0,0 +1,35 @@ +import 'dart:convert'; + +import 'package:http/http.dart'; +import 'package:test_sa/models/lookup.dart'; +import 'package:test_sa/providers/loading_list_notifier.dart'; + +import '../../../controllers/api_routes/api_manager.dart'; +import '../../../controllers/api_routes/urls.dart'; + +class PentryTaskStatusProvider extends LoadingListNotifier { + @override + Future getDate() async { + if (loading ?? false) return -2; + loading = true; + notifyListeners(); + Response response; + try { + response = await ApiManager.instance.get(URLs.getPentryTaskStatus); + } catch (error) { + loading = false; + stateCode = -1; + notifyListeners(); + return -1; + } + stateCode = response.statusCode; + if (response.statusCode >= 200 && response.statusCode < 300) { + // client's request was successfully received + List listJson = json.decode(response.body)["data"]; + items = listJson.map((department) => Lookup.fromJson(department)).toList(); + } + loading = false; + notifyListeners(); + return response.statusCode; + } +} diff --git a/lib/providers/ppm_device_status_provider.dart b/lib/providers/ppm_device_status_provider.dart new file mode 100644 index 00000000..a7eaca05 --- /dev/null +++ b/lib/providers/ppm_device_status_provider.dart @@ -0,0 +1,35 @@ +import 'dart:convert'; + +import 'package:http/http.dart'; +import 'package:test_sa/models/lookup.dart'; + +import '../../controllers/api_routes/api_manager.dart'; +import '../../controllers/api_routes/urls.dart'; +import 'loading_list_notifier.dart'; + +class PPMDeviceStatusProvider extends LoadingListNotifier { + @override + Future getDate() async { + if (loading ?? false) return -2; + loading = true; + notifyListeners(); + Response response; + try { + response = await ApiManager.instance.get(URLs.getPentryStatus); + } catch (error) { + loading = false; + stateCode = -1; + notifyListeners(); + return -1; + } + stateCode = response.statusCode; + if (response.statusCode >= 200 && response.statusCode < 300) { + // client's request was successfully received + List listJson = json.decode(response.body)["data"]; + items = listJson.map((department) => Lookup.fromJson(department)).toList(); + } + loading = false; + notifyListeners(); + return response.statusCode; + } +} diff --git a/lib/providers/ppm_visit_status_provider.dart b/lib/providers/ppm_visit_status_provider.dart new file mode 100644 index 00000000..4e8a5cd5 --- /dev/null +++ b/lib/providers/ppm_visit_status_provider.dart @@ -0,0 +1,35 @@ +import 'dart:convert'; + +import 'package:http/http.dart'; +import 'package:test_sa/models/lookup.dart'; + +import '../../controllers/api_routes/api_manager.dart'; +import '../../controllers/api_routes/urls.dart'; +import 'loading_list_notifier.dart'; + +class PPMVisitStatusProvider extends LoadingListNotifier { + @override + Future getDate() async { + if (loading ?? false) return -2; + loading = true; + notifyListeners(); + Response response; + try { + response = await ApiManager.instance.get(URLs.getPentryVisitStatus); + } catch (error) { + loading = false; + stateCode = -1; + notifyListeners(); + return -1; + } + stateCode = response.statusCode; + if (response.statusCode >= 200 && response.statusCode < 300) { + // client's request was successfully received + List listJson = json.decode(response.body)["data"]; + items = listJson.map((department) => Lookup.fromJson(department)).toList(); + } + loading = false; + notifyListeners(); + return response.statusCode; + } +} diff --git a/lib/views/app_style/colors.dart b/lib/views/app_style/colors.dart index 6afd9b6b..02759ffd 100644 --- a/lib/views/app_style/colors.dart +++ b/lib/views/app_style/colors.dart @@ -112,6 +112,7 @@ class AColors { return AColors.statusDefault; } } + static Color getPriorityStatusColor(int id) { switch (id) { case 81: diff --git a/lib/views/pages/user/land_page.dart b/lib/views/pages/user/land_page.dart index 9f00f6b3..3afdd1a5 100644 --- a/lib/views/pages/user/land_page.dart +++ b/lib/views/pages/user/land_page.dart @@ -25,6 +25,7 @@ import 'package:test_sa/views/widgets/dialogs/dialog.dart'; import 'package:test_sa/views/widgets/drawer/drawer_item.dart'; import 'package:url_launcher/url_launcher.dart'; +import '../../../models/enums/user_types.dart'; import '../../widgets/land_page/land_page_item.dart'; import '../device_transfer/request_device_transfer.dart'; import 'requests/requests_page.dart'; @@ -147,16 +148,15 @@ class _LandPageState extends State { mainAxisSpacing: 12, childAspectRatio: 1, children: [ - /// todo [zaid] : enable this condition when the nurse account works - // if (_userProvider.user != null && _userProvider.user.type == UsersTypes.normal_user) - LandPageItem( - // text: _subtitle.newServiceRequest, - text: "New Service Request", - icon: FontAwesomeIcons.screwdriverWrench, - onPressed: () { - Navigator.of(context).pushNamed(CreateServiceRequestPage.id); - }, - ), + if (_userProvider.user != null && _userProvider.user.type == UsersTypes.normal_user) + LandPageItem( + // text: _subtitle.newServiceRequest, + text: "New Service Request", + icon: FontAwesomeIcons.screwdriverWrench, + onPressed: () { + Navigator.of(context).pushNamed(CreateServiceRequestPage.id); + }, + ), LandPageItem( // text: _subtitle.trackServiceRequest, text: "Track Service Request", @@ -182,16 +182,15 @@ class _LandPageState extends State { // Navigator.of(context).pushNamed(PreventiveMaintenanceVisitsPage.id); // }, // ), - /// todo [zaid] : enable this condition when the nurse account works - // if (_userProvider?.user != null && _userProvider?.user?.type != UsersTypes.engineer) - LandPageItem( - text: "Request Gas Refill", - icon: FontAwesomeIcons.truckFast, - onPressed: () { - // Navigator.of(context).pushNamed(RequestGasRefill.id); - Navigator.of(context).pushNamed(NewGasRefillRequestPage.routeName); - }, - ), + if (_userProvider?.user != null && _userProvider?.user?.type != UsersTypes.engineer) + LandPageItem( + text: "Request Gas Refill", + icon: FontAwesomeIcons.truckFast, + onPressed: () { + // Navigator.of(context).pushNamed(RequestGasRefill.id); + Navigator.of(context).pushNamed(NewGasRefillRequestPage.routeName); + }, + ), LandPageItem( text: "Track Gas Refill", icon: Icons.content_paste_search, @@ -213,16 +212,14 @@ class _LandPageState extends State { Navigator.of(context).pushNamed(TrackDeviceTransferPage.id); }, ), - - /// todo [zaid] : enable this condition when the nurse account works - // if (_userProvider?.user != null && _userProvider?.user?.type != UsersTypes.normal_user) - LandPageItem( - text: "Create Sub Work Order", - svgPath: "assets/images/sub_workorder_icon.svg", - onPressed: () { - Navigator.of(context).pushNamed(SearchSubWorkOrderPage.id); - }, - ), + if (_userProvider?.user != null && _userProvider?.user?.type != UsersTypes.normal_user) + LandPageItem( + text: "Create Sub Work Order", + svgPath: "assets/images/sub_workorder_icon.svg", + onPressed: () { + Navigator.of(context).pushNamed(SearchSubWorkOrderPage.id); + }, + ), ], ), ], diff --git a/lib/views/pages/user/requests/work_order/work_order_details_page.dart b/lib/views/pages/user/requests/work_order/work_order_details_page.dart index cd9d9ab1..195b6c00 100644 --- a/lib/views/pages/user/requests/work_order/work_order_details_page.dart +++ b/lib/views/pages/user/requests/work_order/work_order_details_page.dart @@ -14,7 +14,6 @@ import '../../../../../controllers/providers/api/user_provider.dart'; import '../../../../../models/enums/user_types.dart'; import '../../../../../models/service_request/search_work_order.dart'; import '../../../../widgets/requests/request_status.dart'; -import 'update_service_report.dart'; class WorkOrderDetailsPage extends StatelessWidget { static const String id = "/work_order_details_page"; @@ -70,17 +69,13 @@ class WorkOrderDetailsPage extends StatelessWidget { Text('${context.translation.site}: ${workOrder.callRequest.asset.site.custName ?? ""}', style: AppTextStyles.bodyText.copyWith(color: const Color(0xFF757575))), Text('${"Call last Situation"}: ${workOrder.calllastSituation.name ?? '' ?? ""}', style: AppTextStyles.bodyText.copyWith(color: const Color(0xFF757575))), ], - ).paddingAll(16).onPress(() { - // onPressed(request); - }), + ).paddingAll(16), ), ).expanded, if (userProvider.user.type == UsersTypes.engineer && serviceRequest.statusValue != 5 && serviceRequest.statusValue != 3) AppFilledButton( onPressed: () { - Navigator.of(context).push( - MaterialPageRoute(builder: (_) => UpdateServiceReport(request: serviceRequest, workOrder: workOrder)), - ); + Navigator.of(context).push(MaterialPageRoute(builder: (_) => Container())); }, label: context.translation.updateRequest, ).paddingAll(16), diff --git a/lib/views/pages/user/visits/pantry/edit_pentry.dart b/lib/views/pages/user/visits/pantry/edit_pentry.dart index 1ccf44c2..38fd4aa3 100644 --- a/lib/views/pages/user/visits/pantry/edit_pentry.dart +++ b/lib/views/pages/user/visits/pantry/edit_pentry.dart @@ -1,24 +1,25 @@ import 'package:flutter/material.dart'; -import 'package:fluttertoast/fluttertoast.dart'; import 'package:provider/provider.dart'; -import 'package:test_sa/controllers/localization/localization.dart'; import 'package:test_sa/controllers/providers/api/regular_visits_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/context_extension.dart'; +import 'package:test_sa/extensions/int_extensions.dart'; +import 'package:test_sa/extensions/widget_extensions.dart'; import 'package:test_sa/models/pantry/calibration_tools.dart'; import 'package:test_sa/models/pantry/pentry.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/subtitle.dart'; import 'package:test_sa/models/visits/visit.dart'; -import 'package:test_sa/views/widgets/buttons/app_small_button.dart'; +import 'package:test_sa/new_views/app_style/app_color.dart'; +import 'package:test_sa/new_views/common_widgets/app_filled_button.dart'; +import 'package:test_sa/new_views/common_widgets/default_app_bar.dart'; import 'package:test_sa/views/widgets/loaders/loading_manager.dart'; import 'package:test_sa/views/widgets/pentry/pentry_calibration_tool_form.dart'; import 'package:test_sa/views/widgets/pentry/pentry_pm_kit_form.dart'; import 'package:test_sa/views/widgets/pentry/pentry_ppm_check_list_form.dart'; -import '../../../../widgets/pentry/pentry_info_form.dart'; +import '../../../../widgets/pentry/pentry_tbs_form.dart'; class EditPentry extends StatefulWidget { final Pentry pentry; @@ -48,25 +49,9 @@ class _EditPentryState extends State with SingleTickerProviderStateM setState(() {}); return; } - _isLoading = true; - setState(() {}); + _pentry.clearEmptyObjects(); - int status = await _regularVisitsProvider.updatePentry(user: _userProvider.user, host: _settingProvider.host, pentry: _pentry, visit: widget.visit); - _isLoading = false; - setState(() {}); - if (status >= 200 && status < 300) { - Fluttertoast.showToast( - msg: context.translation.successfulRequestMessage, - ); - Navigator.of(context).pop(); - Navigator.of(context).pop(); - } else { - // String errorMessage = HttpStatusManger.getStatusMessage( - // status: status, subtitle: context.translation); - // Fluttertoast.showToast( - // msg: errorMessage, - // ); - } + await _regularVisitsProvider.updatePentry(context, user: _userProvider.user, pentry: _pentry, visit: widget.visit); } @override @@ -91,109 +76,61 @@ class _EditPentryState extends State with SingleTickerProviderStateM _settingProvider = Provider.of(context); _regularVisitsProvider = Provider.of(context); return Scaffold( + appBar: DefaultAppBar(title: context.translation.preventiveMaintenance), key: _scaffoldKey, body: SafeArea( child: LoadingManager( - isLoading: _isLoading, - isFailedLoading: false, - stateCode: 200, - onRefresh: () async {}, - child: Column( - children: [ - Material( - color: Theme.of(context).colorScheme.primary, - child: Padding( - padding: const EdgeInsets.all(2.0), - child: TabBar( - controller: _tabController, - isScrollable: true, - onTap: (index) { - setState(() {}); - }, - tabs: const [ - Tab( - text: "PPM Check List", - ), - Tab( - text: "Calibration Tools", - ), - Tab( - text: "PM Kits", - ), - Tab( - text: "PM Entry", - ), - ], - ), - ), - ), - Expanded( - child: Stack( - children: [ - TabBarView( - physics: const NeverScrollableScrollPhysics(), - controller: _tabController, - children: [ - PentryPPMCheckListForm( - models: _pentry.ppmCheckLists, - enableValidate: _validate, - ), - PentryCalibrationToolForm( - models: _pentry.calibrationTools, - enableValidate: _validate, - ), - PentryPMKitForm( - models: _pentry.pmKits, - enableValidate: _validate, - assetId: widget.visit?.deviceId, - ), - PentryInfoForm( - model: _pentry, - enableValidate: _validate, - ), - ], - ), - Align( - alignment: Alignment.bottomCenter, - child: Padding( - padding: const EdgeInsets.all(8.0), - child: Row( - children: [ - if (_tabController.index != 0) - ASmallButton( - text: context.translation.back, - onPressed: () { - _tabController.animateTo( - _tabController.index - 1, - ); - setState(() {}); - }, - ), - const Spacer(), - if (_tabController.index != _tabController.length - 1) - ASmallButton( - text: context.translation.next, - onPressed: () { - _tabController.animateTo( - _tabController.index + 1, - ); - setState(() {}); - }, - ), - if (_tabController.index == _tabController.length - 1) - ASmallButton( - text: context.translation.update, - onPressed: _onSubmit, - ), - ], - ), - ), - ) - ], - ), + isLoading: _isLoading, + isFailedLoading: false, + stateCode: 200, + onRefresh: () async {}, + child: Column( + children: [ + Container( + decoration: BoxDecoration(color: AppColor.neutral30, borderRadius: BorderRadius.circular(16)), + child: TabBar( + controller: _tabController, + isScrollable: true, + padding: EdgeInsets.zero, + labelColor: AppColor.neutral60, + unselectedLabelColor: AppColor.neutral20, + indicatorPadding: const EdgeInsets.all(4), + indicator: BoxDecoration(color: Theme.of(context).cardColor, borderRadius: BorderRadius.circular(13)), + onTap: (index) { + setState(() {}); + }, + tabs: [ + Tab(text: "TBS", height: 57.toScreenHeight), + Tab(text: "Calibration Tool", height: 57.toScreenHeight), + Tab(text: "PM Kit", height: 57.toScreenHeight), + Tab(text: "PPM Checklist", height: 57.toScreenHeight), + ], ), - ], - )), + ), + TabBarView( + physics: const NeverScrollableScrollPhysics(), + controller: _tabController, + children: [ + PentryTBSForm(model: _pentry, enableValidate: _validate), + PentryCalibrationToolForm(models: _pentry.calibrationTools, enableValidate: _validate), + PentryPMKitForm(models: _pentry.pmKits, enableValidate: _validate, assetId: widget.visit?.deviceId), + PentryPMChecklistForm(models: _pentry.ppmCheckLists, enableValidate: _validate), + ], + ).expanded, + AppFilledButton( + onPressed: () { + if (_tabController.index == 3) { + _onSubmit(); + } else { + _tabController.animateTo(_tabController.index + 1); + setState(() {}); + } + }, + label: _tabController.index == 3 ? context.translation.submit : context.translation.next, + ).paddingOnly(top: 16), + ], + ).paddingAll(16), + ), ), ); } diff --git a/lib/views/pages/user/visits/pantry/future_edit_pently.dart b/lib/views/pages/user/visits/pantry/future_edit_pently.dart index dca08d02..8343904c 100644 --- a/lib/views/pages/user/visits/pantry/future_edit_pently.dart +++ b/lib/views/pages/user/visits/pantry/future_edit_pently.dart @@ -1,12 +1,10 @@ import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; -import 'package:test_sa/controllers/localization/localization.dart'; import 'package:test_sa/controllers/providers/api/regular_visits_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/context_extension.dart'; import 'package:test_sa/models/pantry/pentry.dart'; -import 'package:test_sa/models/subtitle.dart'; import 'package:test_sa/models/visits/visit.dart'; import 'package:test_sa/views/pages/user/visits/pantry/edit_pentry.dart'; import 'package:test_sa/views/widgets/loaders/app_loading.dart'; @@ -32,7 +30,7 @@ class _FutureEditPentryState extends State { return Scaffold( body: FutureBuilder( - future: RegularVisitsProvider().getPently(user: _userProvider.user, host: _settingProvider.host, id: widget.visit.id), + future: RegularVisitsProvider().getPentry(user: _userProvider.user, host: _settingProvider.host, id: widget.visit.id), builder: (BuildContext context, AsyncSnapshot snapshot) { if (snapshot.hasError) { return FailedLoading( diff --git a/lib/views/pages/user/visits/regular_visits_page.dart b/lib/views/pages/user/visits/regular_visits_page.dart index 628dd099..0a9edb13 100644 --- a/lib/views/pages/user/visits/regular_visits_page.dart +++ b/lib/views/pages/user/visits/regular_visits_page.dart @@ -3,21 +3,14 @@ import 'package:flutter/material.dart'; import 'package:fluttertoast/fluttertoast.dart'; import 'package:provider/provider.dart'; import 'package:test_sa/controllers/api_routes/http_status_manger.dart'; -import 'package:test_sa/controllers/localization/localization.dart'; import 'package:test_sa/controllers/providers/api/regular_visits_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/context_extension.dart'; -import 'package:test_sa/models/subtitle.dart'; import 'package:test_sa/models/visits/visits_group.dart'; -import 'package:test_sa/models/visits/visits_search.dart'; -import 'package:test_sa/views/app_style/colors.dart'; +import 'package:test_sa/new_views/common_widgets/default_app_bar.dart'; import 'package:test_sa/views/pages/user/visits/update_visits_group_sheet.dart'; -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/loaders/loading_manager.dart'; -import 'package:test_sa/views/widgets/search/visits_search_bar.dart'; import 'package:test_sa/views/widgets/visits/visits_list.dart'; class RegularVisitsPage extends StatefulWidget { @@ -40,6 +33,7 @@ class _RegularVisitsPageState extends State with TickerProvid _userProvider = Provider.of(context); return Scaffold( + appBar: DefaultAppBar(title: context.translation.preventiveMaintenance), body: SafeArea( child: LoadingManager( isLoading: _visitsProvider.isLoading, @@ -53,128 +47,177 @@ class _RegularVisitsPageState extends State with TickerProvid host: _settingProvider.host, ); }, - child: Stack( - children: [ - Column( - children: [ - Container( - color: AColors.primaryColor, - padding: const EdgeInsets.symmetric(horizontal: 0, vertical: 4), - child: Column( - children: [ - Row( - children: [ - ABackButton(), - Expanded( - child: Center( - child: Text( - context.translation.preventiveMaintenance, - style: Theme.of(context).textTheme.headline6.copyWith(color: AColors.white, fontStyle: FontStyle.italic), - ), - ), - ), - AnimatedSwitcher( - duration: Duration(milliseconds: 400), - child: AIconButton( - key: ValueKey(_expandedSearch), - iconData: _expandedSearch ? Icons.keyboard_arrow_up : Icons.search, - color: AColors.secondaryColor, - buttonSize: 42, - backgroundColor: AColors.white, - onPressed: () async { - VisitsSearch _temp = await showModalBottomSheet( - context: context, - isScrollControlled: true, - builder: (context) { - return VisitsSearchDialog( - initialSearchValue: _visitsProvider.visitsSearch, - ); - }); - if (_temp != null) { - _visitsProvider.visitsSearch.fromSearch(_temp); - _visitsProvider.reset(); - setState(() {}); - } - }, - ), - ), - SizedBox( - width: 16, - ) - ], - ), - ], - ), - ), - Visibility( - visible: (_visitsProvider.visitsSearch.toMap()..remove("mostRecent")).isNotEmpty, - child: Padding( - padding: const EdgeInsets.all(8.0), - child: AButton( - text: context.translation.clearSearch, - onPressed: () { - _visitsProvider.visitsSearch = VisitsSearch(); - _visitsProvider.reset(); - setState(() {}); - }, - ), - ), - ), - Expanded( - child: VisitsList( - nextPage: _visitsProvider.nextPage, - onLazyLoad: () async { - await _visitsProvider.getVisits( - user: _userProvider.user, - host: _settingProvider.host, - ); - }, - onEditGroup: (visits) async { - VisitsGroup _group = await showModalBottomSheet( - isScrollControlled: true, - context: context, - builder: (context) { - return UpdateVisitsGroupSheet( - visits: visits, - title: context.translation.updateRegularVisits, - ); - }, - ) as VisitsGroup; - if (_group != null) { - showDialog( - context: context, - barrierDismissible: false, - builder: (BuildContext context) { - return CupertinoAlertDialog( - title: Text(context.translation.updatingDots), - content: Center(child: CircularProgressIndicator()), - ); - }, - ); - int status = await _visitsProvider.updateGroupOfVisits(user: _userProvider.user, host: _settingProvider.host, group: _group); - Navigator.of(context).pop(); - if (status >= 200 && status < 300) { - Fluttertoast.showToast( - msg: context.translation.preventiveMaintenanceUpdatedSuccessfully, - toastLength: Toast.LENGTH_LONG, - gravity: ToastGravity.BOTTOM, - ); - } else { - Fluttertoast.showToast( - msg: HttpStatusManger.getStatusMessage(status: status, subtitle: context.translation), - toastLength: Toast.LENGTH_LONG, - gravity: ToastGravity.BOTTOM, - ); - } - } - }, - visits: _visitsProvider.visits, - ), - ), - ], - ), - ], + child: VisitsList( + nextPage: _visitsProvider.nextPage, + onLazyLoad: () async { + await _visitsProvider.getVisits( + user: _userProvider.user, + host: _settingProvider.host, + ); + }, + onEditGroup: (visits) async { + VisitsGroup group = await showModalBottomSheet( + isScrollControlled: true, + context: context, + builder: (context) { + return UpdateVisitsGroupSheet( + visits: visits, + title: context.translation.updateRegularVisits, + ); + }, + ) as VisitsGroup; + if (group != null) { + showDialog( + context: context, + barrierDismissible: false, + builder: (BuildContext context) { + return CupertinoAlertDialog( + title: Text(context.translation.updatingDots), + content: Center(child: CircularProgressIndicator()), + ); + }, + ); + int status = await _visitsProvider.updateGroupOfVisits(user: _userProvider.user, host: _settingProvider.host, group: group); + Navigator.of(context).pop(); + if (status >= 200 && status < 300) { + Fluttertoast.showToast( + msg: context.translation.preventiveMaintenanceUpdatedSuccessfully, + toastLength: Toast.LENGTH_LONG, + gravity: ToastGravity.BOTTOM, + ); + } else { + Fluttertoast.showToast( + msg: HttpStatusManger.getStatusMessage(status: status, subtitle: context.translation), + toastLength: Toast.LENGTH_LONG, + gravity: ToastGravity.BOTTOM, + ); + } + } + }, + visits: _visitsProvider.visits, ), + // child: Stack( + // children: [ + // Column( + // children: [ + // Container( + // color: AColors.primaryColor, + // padding: const EdgeInsets.symmetric(horizontal: 0, vertical: 4), + // child: Column( + // children: [ + // Row( + // children: [ + // ABackButton(), + // Expanded( + // child: Center( + // child: Text( + // context.translation.preventiveMaintenance, + // style: Theme.of(context).textTheme.headline6.copyWith(color: AColors.white, fontStyle: FontStyle.italic), + // ), + // ), + // ), + // AnimatedSwitcher( + // duration: Duration(milliseconds: 400), + // child: AIconButton( + // key: ValueKey(_expandedSearch), + // iconData: _expandedSearch ? Icons.keyboard_arrow_up : Icons.search, + // color: AColors.secondaryColor, + // buttonSize: 42, + // backgroundColor: AColors.white, + // onPressed: () async { + // VisitsSearch _temp = await showModalBottomSheet( + // context: context, + // isScrollControlled: true, + // builder: (context) { + // return VisitsSearchDialog( + // initialSearchValue: _visitsProvider.visitsSearch, + // ); + // }); + // if (_temp != null) { + // _visitsProvider.visitsSearch.fromSearch(_temp); + // _visitsProvider.reset(); + // setState(() {}); + // } + // }, + // ), + // ), + // SizedBox( + // width: 16, + // ) + // ], + // ), + // ], + // ), + // ), + // Visibility( + // visible: (_visitsProvider.visitsSearch.toMap()..remove("mostRecent")).isNotEmpty, + // child: Padding( + // padding: const EdgeInsets.all(8.0), + // child: AButton( + // text: context.translation.clearSearch, + // onPressed: () { + // _visitsProvider.visitsSearch = VisitsSearch(); + // _visitsProvider.reset(); + // setState(() {}); + // }, + // ), + // ), + // ), + // Expanded( + // child: VisitsList( + // nextPage: _visitsProvider.nextPage, + // onLazyLoad: () async { + // await _visitsProvider.getVisits( + // user: _userProvider.user, + // host: _settingProvider.host, + // ); + // }, + // onEditGroup: (visits) async { + // VisitsGroup _group = await showModalBottomSheet( + // isScrollControlled: true, + // context: context, + // builder: (context) { + // return UpdateVisitsGroupSheet( + // visits: visits, + // title: context.translation.updateRegularVisits, + // ); + // }, + // ) as VisitsGroup; + // if (_group != null) { + // showDialog( + // context: context, + // barrierDismissible: false, + // builder: (BuildContext context) { + // return CupertinoAlertDialog( + // title: Text(context.translation.updatingDots), + // content: Center(child: CircularProgressIndicator()), + // ); + // }, + // ); + // int status = await _visitsProvider.updateGroupOfVisits(user: _userProvider.user, host: _settingProvider.host, group: _group); + // Navigator.of(context).pop(); + // if (status >= 200 && status < 300) { + // Fluttertoast.showToast( + // msg: context.translation.preventiveMaintenanceUpdatedSuccessfully, + // toastLength: Toast.LENGTH_LONG, + // gravity: ToastGravity.BOTTOM, + // ); + // } else { + // Fluttertoast.showToast( + // msg: HttpStatusManger.getStatusMessage(status: status, subtitle: context.translation), + // toastLength: Toast.LENGTH_LONG, + // gravity: ToastGravity.BOTTOM, + // ); + // } + // } + // }, + // visits: _visitsProvider.visits, + // ), + // ), + // ], + // ), + // ], + // ), ), ), ); diff --git a/lib/views/pages/user/visits/visit_details.dart b/lib/views/pages/user/visits/visit_details.dart index 6b9499da..dea919cc 100644 --- a/lib/views/pages/user/visits/visit_details.dart +++ b/lib/views/pages/user/visits/visit_details.dart @@ -1,22 +1,19 @@ import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; -import 'package:test_sa/controllers/localization/localization.dart'; import 'package:test_sa/extensions/context_extension.dart'; +import 'package:test_sa/extensions/int_extensions.dart'; +import 'package:test_sa/extensions/string_extensions.dart'; +import 'package:test_sa/extensions/text_extensions.dart'; import 'package:test_sa/extensions/widget_extensions.dart'; import 'package:test_sa/models/visits/visit.dart'; -import 'package:test_sa/views/app_style/colors.dart'; -import 'package:test_sa/views/app_style/sizing.dart'; +import 'package:test_sa/new_views/common_widgets/default_app_bar.dart'; import 'package:test_sa/views/pages/user/visits/pantry/edit_pentry.dart'; -import 'package:test_sa/views/widgets/buttons/app_back_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/requests/info_row.dart'; -import 'package:test_sa/views/widgets/visits/visit_status.dart'; import '../../../../controllers/providers/api/user_provider.dart'; import '../../../../models/enums/user_types.dart'; -import '../../../widgets/loaders/image_loader.dart'; +import '../../../../new_views/common_widgets/app_filled_button.dart'; +import '../../../app_style/colors.dart'; +import '../../../widgets/requests/request_status.dart'; class VisitDetailsPage extends StatelessWidget { static const String id = "/visit-details"; @@ -29,149 +26,64 @@ class VisitDetailsPage extends StatelessWidget { UserProvider userProvider = Provider.of(context); return Scaffold( + appBar: DefaultAppBar(title: context.translation.preventiveMaintenance), body: SafeArea( child: Column( children: [ - Container( - color: AColors.primaryColor, - padding: const EdgeInsets.symmetric(horizontal: 0, vertical: 4), - child: Row( - children: [ - const ABackButton(), - Expanded( - child: Center( - child: Text( - context.translation.visitInformation, - style: Theme.of(context).textTheme.titleLarge.copyWith(color: AColors.white, fontStyle: FontStyle.italic), - ), - ), - ), - if (userProvider?.user?.type == UsersTypes.engineer) - AIconButton( - iconData: Icons.edit, - color: AColors.white, - buttonSize: 42, - backgroundColor: AColors.green, - onPressed: visit?.status?.name == "Closed" || visit?.status?.name == "Complete" - ? null - : () async { - Navigator.of(context).push( - MaterialPageRoute( - builder: (_) => EditPentry( - visit: visit, - pentry: visit.pentry, - ), - ), - ); - }, - ), - const SizedBox(width: 42) - ], - ), - ), - Expanded( - child: ListView( - padding: const EdgeInsets.symmetric(horizontal: 16), - children: [ - const SizedBox(height: 8), - // MaterialButton( - // padding: EdgeInsets.zero, - // onPressed: () { - // if ((visit.images?.isNotEmpty ?? false) && (visit.images?.first?.isNotEmpty ?? false)) { - // Navigator.of(context).push( - // MaterialPageRoute( - // builder: (_) => Scaffold( - // body: InteractiveViewer( - // child: Center( - // child: ImageLoader( - // url: visit.images.first, - // boxFit: BoxFit.contain, - // ), - // ), - // ), - // ), - // ), - // ); - // } - // }, - // child: SizedBox( - // height: 140 * AppStyle.getScaleFactor(context), - // width: MediaQuery.of(context).size.width, - // child: ImageLoader( - // url: visit.images.isEmpty ? " " : visit.images.first, - // boxFit: BoxFit.cover, - // ), - // ), - // ), - // const SizedBox( - // height: 8, - // ), - if (visit?.images?.isNotEmpty ?? false) - SizedBox( - height: 60 * AppStyle.getScaleFactor(context), - child: FilesList( - images: visit.images, - ), - ).paddingOnly(top: 4, bottom: 4), - const SizedBox( - height: 8, - ), - RequestInfoRow( - title: context.translation.code, - info: visit.serialNumber, - ), - RequestInfoRow( - title: "Asset Number", - info: visit.deviceNumber, - ), - RequestInfoRow( - title: context.translation.deviceName, - content: visit.deviceEnglishName, - ), - RequestInfoRow( - title: context.translation.deviceSN, - info: visit.deviceSerialNumber, - ), - RequestInfoRow( - title: context.translation.expectDate, - info: visit.expectDate, - ), - RequestInfoRow( - title: context.translation.actualDate, - info: visit.actualDate, - ), - Row( - children: [ - Expanded( - child: Text( - "${context.translation.status} : ", - style: Theme.of(context).textTheme.titleMedium.copyWith(fontWeight: FontWeight.bold), - textScaleFactor: AppStyle.getScaleFactor(context), + SingleChildScrollView( + child: Container( + margin: const EdgeInsets.all(16), + width: double.infinity, + decoration: ShapeDecoration( + color: Colors.white, + shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(20)), + shadows: const [BoxShadow(color: Color(0x07000000), blurRadius: 14, offset: Offset(0, 0), spreadRadius: 0)], + ), + child: Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + children: [ + // StatusLabel( + // label: visit.priority.name, + // id: visit.priority.id, + // textColor: AColors.getPriorityStatusTextColor(visit.priority.id), + // backgroundColor: AColors.getPriorityStatusColor(visit.priority.id)), + // 8.width, + StatusLabel( + label: visit.status.name, + id: visit.status.id, + textColor: AColors.getRequestStatusTextColor(visit.status.value), + backgroundColor: AColors.getRequestStatusColor(visit.status.value), ), - ), - VisitStatusLabel( - visit: visit, - ), - ], - ), - Divider( - color: Theme.of(context).primaryColor, - ), - RequestInfoRow( - title: context.translation.contactStatus, - info: visit.assignTo, - ), - RequestInfoRow( - title: context.translation.engineerName, - info: visit.employName, - ), - RequestInfoRow( - title: context.translation.hospital, - content: visit.hospitalName, - ), - ], + 1.width.expanded, + ], + ), + 8.height, + Text(visit.deviceEnglishName, style: AppTextStyles.heading5.copyWith(color: const Color(0xFF3B3D4A))), + 8.height, + Text('${context.translation.assetNumber}: ${visit.deviceNumber}', style: AppTextStyles.bodyText.copyWith(color: const Color(0xFF757575))), + Text('Asset Serial No.: ${visit.deviceSerialNumber}', style: AppTextStyles.bodyText.copyWith(color: const Color(0xFF757575))), + Text('Code: ${visit.serialNumber}', style: AppTextStyles.bodyText.copyWith(color: const Color(0xFF757575))), + const Divider().defaultStyle(context), + Text('Expected Date: ${visit.expectDate?.toServiceRequestDetailsFormat}', style: AppTextStyles.bodyText.copyWith(color: const Color(0xFF757575))), + Text('Actual Date: ${visit.actualDate?.toServiceRequestDetailsFormat}', style: AppTextStyles.bodyText.copyWith(color: const Color(0xFF757575))), + const Divider().defaultStyle(context), + Text('Assigned to: ${visit.assignTo}', style: AppTextStyles.bodyText.copyWith(color: const Color(0xFF757575))), + Text('Engineer Name: ${visit.employName}', style: AppTextStyles.bodyText.copyWith(color: const Color(0xFF757575))), + Text('Site: ${visit.hospitalName}', style: AppTextStyles.bodyText.copyWith(color: const Color(0xFF757575))), + ], + ).paddingAll(16), ), - ), + ).expanded, + if (userProvider.user.type == UsersTypes.engineer && visit.status.value != 5 && visit.status.value != 3) + AppFilledButton( + onPressed: () { + Navigator.of(context).push(MaterialPageRoute(builder: (_) => EditPentry(visit: visit, pentry: visit.pentry))); + }, + label: context.translation.updateRequest, + ).paddingAll(16), ], ), ), diff --git a/lib/views/widgets/parts/auto_complete_parts_field.dart b/lib/views/widgets/parts/auto_complete_parts_field.dart index 7bd26d30..cc94e248 100644 --- a/lib/views/widgets/parts/auto_complete_parts_field.dart +++ b/lib/views/widgets/parts/auto_complete_parts_field.dart @@ -1,11 +1,13 @@ import 'package:flutter/material.dart'; +import 'package:flutter_typeahead/flutter_typeahead.dart'; import 'package:provider/provider.dart'; import 'package:test_sa/controllers/providers/api/parts_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/views/app_style/colors.dart'; +import 'package:test_sa/extensions/context_extension.dart'; import 'package:test_sa/views/app_style/sizing.dart'; +import '../../../extensions/text_extensions.dart'; import '../../../models/service_request/spare_parts.dart'; class AutoCompletePartsField extends StatefulWidget { @@ -32,6 +34,14 @@ class _AutoCompletePartsFieldState extends State { super.initState(); } + @override + void didUpdateWidget(covariant AutoCompletePartsField oldWidget) { + if (widget.initialValue != oldWidget.initialValue) { + _controller = TextEditingController(text: widget.initialValue); + } + super.didUpdateWidget(oldWidget); + } + @override void dispose() { _controller.dispose(); @@ -47,17 +57,17 @@ class _AutoCompletePartsFieldState extends State { return 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: - Container() /*TypeAheadField( + color: Colors.white, + borderRadius: BorderRadius.circular(AppStyle.borderRadius * AppStyle.getScaleFactor(context)), + boxShadow: [BoxShadow(color: Colors.black.withOpacity(0.05), blurRadius: 10)], + ), + child: TypeAheadField( textFieldConfiguration: TextFieldConfiguration( - style: Theme.of(context).textTheme.subtitle1, + style: AppTextStyles.bodyText, controller: _controller, - textAlign: TextAlign.center, - decoration: const InputDecoration( + textAlign: TextAlign.start, + decoration: InputDecoration( + label: context.translation.partNumberName.tinyFont(context), border: InputBorder.none, disabledBorder: InputBorder.none, focusedBorder: InputBorder.none, @@ -66,14 +76,14 @@ class _AutoCompletePartsFieldState extends State { textInputAction: TextInputAction.search, ), suggestionsCallback: (vale) async { - return await _partsProvider.getPartsList(title: vale, assetId: widget.assetId); + return (await _partsProvider.getPartsList(title: vale, assetId: widget.assetId)).map((e) => SparePartsWorkOrders(sparePart: e)).toList(); }, itemBuilder: (context, part) { return ListTile( title: Text(part?.sparePart?.partNo ?? ""), subtitle: Text( part?.sparePart?.partName ?? "", - style: Theme.of(context).textTheme.caption, + style: Theme.of(context).textTheme.bodySmall, ), ); }, @@ -85,8 +95,7 @@ class _AutoCompletePartsFieldState extends State { } widget.onPick(part); }, - )*/ - , + ), ); } } diff --git a/lib/views/widgets/pentry/auto_complete_fields/auto_complete_devices_field.dart b/lib/views/widgets/pentry/auto_complete_fields/auto_complete_devices_field.dart index 397c7ec2..8fe86d6c 100644 --- a/lib/views/widgets/pentry/auto_complete_fields/auto_complete_devices_field.dart +++ b/lib/views/widgets/pentry/auto_complete_fields/auto_complete_devices_field.dart @@ -4,8 +4,10 @@ import 'package:provider/provider.dart'; import 'package:test_sa/controllers/providers/api/devices_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/context_extension.dart'; +import 'package:test_sa/extensions/text_extensions.dart'; +import 'package:test_sa/extensions/widget_extensions.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'; import '../../../../models/device/asset.dart'; @@ -33,6 +35,14 @@ class _AutoCompleteDeviceNumberFieldState extends State( textFieldConfiguration: TextFieldConfiguration( - style: Theme.of(context).textTheme.headline6, + style: AppTextStyles.bodyText, controller: _controller, - textAlign: TextAlign.center, - decoration: const InputDecoration( + textAlign: TextAlign.start, + decoration: InputDecoration( + label: context.translation.assetNumber.tinyFont(context), border: InputBorder.none, disabledBorder: InputBorder.none, focusedBorder: InputBorder.none, @@ -74,10 +85,7 @@ class _AutoCompleteDeviceNumberFieldState extends State models; final bool enableValidate; - const PentryCalibrationToolForm({ - Key key, - this.models, - this.enableValidate, - }) : super(key: key); + const PentryCalibrationToolForm({Key key, this.models, this.enableValidate}) : super(key: key); @override State createState() => _PentryCalibrationToolFormState(); @@ -27,48 +24,46 @@ class PentryCalibrationToolForm extends StatefulWidget { class _PentryCalibrationToolFormState extends State { @override Widget build(BuildContext context) { - final userProvider = Provider.of(context); return ListView.builder( - padding: EdgeInsets.only( - top: 12 * AppStyle.getScaleFactor(context), left: 12 * AppStyle.getScaleFactor(context), right: 12 * AppStyle.getScaleFactor(context), bottom: 80 * AppStyle.getScaleFactor(context)), - itemCount: widget.models.length + 1, - itemBuilder: (context, index) { - if (index == widget.models.length) { - return AButton( - text: context.translation.add, - onPressed: () { - widget.models.add(CalibrationTool()); - setState(() {}); - }, - ); - } - final model = widget.models[index]; - return Column( + itemCount: widget.models.length + 1, + padding: EdgeInsets.only(top: 16.toScreenHeight), + itemBuilder: (context, index) { + if (index == widget.models.length) { + return AppFilledButton( + label: "Add Asset", + maxWidth: true, + textColor: Colors.white, + buttonColor: context.isDark ? AppColor.neutral60 : AppColor.neutral50, + onPressed: () { + widget.models.add(CalibrationTool()); + setState(() {}); + }, + ); + } + final model = widget.models[index]; + return Container( + padding: const EdgeInsets.all(16), + margin: EdgeInsets.only(bottom: 16.toScreenHeight), + decoration: BoxDecoration( + color: Theme.of(context).cardColor, + borderRadius: BorderRadius.circular(20), + boxShadow: [BoxShadow(color: Colors.black.withOpacity(0.03), blurRadius: 14)], + ), + child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - ASubTitle("#${index + 1}"), - if (index != 0) - ASmallButton( - color: Theme.of(context).colorScheme.error, - text: context.translation.delete, - onPressed: () { - widget.models.remove(model); - setState(() {}); - }, - ), + "Asset ${index + 1}".heading5(context), + "trash".toSvgAsset(height: 20, width: 15).onPress(() { + widget.models.remove(model); + setState(() {}); + }), ], ), - const SizedBox( - height: 8, - ), - const ASubTitle("Asset Number"), - const SizedBox( - height: 4, - ), + 16.height, AutoCompleteDeviceNumberField( initialValue: model.assetsNumber, hospitalId: userProvider.user.clientId, @@ -76,28 +71,19 @@ class _PentryCalibrationToolFormState extends State { model.assetsNumber = number; }, ), - const SizedBox( - height: 8, - ), - const ASubTitle("Date of Testing"), - const SizedBox( - height: 4, - ), + 8.height, ADatePicker( + label: "Calibration Date", date: model.dataOfTesting, onDatePicker: (date) { model.dataOfTesting = date; setState(() {}); }, ), - const SizedBox( - height: 8, - ), - Divider( - color: Theme.of(context).textTheme.titleMedium.color, - ), ], - ); - }); + ), + ); + }, + ); } } diff --git a/lib/views/widgets/pentry/pentry_info_form.dart b/lib/views/widgets/pentry/pentry_info_form.dart deleted file mode 100644 index f38b1fbc..00000000 --- a/lib/views/widgets/pentry/pentry_info_form.dart +++ /dev/null @@ -1,209 +0,0 @@ -import 'dart:convert'; - -import 'package:flutter/material.dart'; -import 'package:provider/provider.dart'; -import 'package:test_sa/controllers/providers/api/user_provider.dart'; -import 'package:test_sa/extensions/context_extension.dart'; -import 'package:test_sa/models/pantry/pentry.dart'; -import 'package:test_sa/views/app_style/sizing.dart'; -import 'package:test_sa/views/widgets/app_text_form_field.dart'; -import 'package:test_sa/views/widgets/date_and_time/date_picker.dart'; -import 'package:test_sa/views/widgets/e_signature/e_signature.dart'; -import 'package:test_sa/views/widgets/status/pentry/pentry_visit_status_mune.dart'; -import 'package:test_sa/views/widgets/timer/app_timer.dart'; -import 'package:test_sa/views/widgets/titles/app_sub_title.dart'; - -import '../images/multi_image_picker.dart'; -import '../status/pentry/pentry_status_mune.dart'; - -class PentryInfoForm extends StatefulWidget { - final Pentry model; - final bool enableValidate; - - const PentryInfoForm({ - Key key, - this.model, - this.enableValidate, - }) : super(key: key); - - @override - State createState() => _PentryInfoFormState(); -} - -class _PentryInfoFormState extends State { - @override - Widget build(BuildContext context) { - widget.model?.files ??= []; - - final userProvider = Provider.of(context); - return Padding( - padding: EdgeInsets.only( - top: 12 * AppStyle.getScaleFactor(context), left: 12 * AppStyle.getScaleFactor(context), right: 12 * AppStyle.getScaleFactor(context), bottom: 80 * AppStyle.getScaleFactor(context)), - child: SingleChildScrollView( - child: Column( - crossAxisAlignment: CrossAxisAlignment.stretch, - children: [ - const SizedBox( - height: 8, - ), - const ASubTitle("PPM Visit Status"), - if (widget.enableValidate && widget.model.ppmVisitStatus == null) - ASubTitle( - context.translation.requiredWord, - color: Colors.red, - ), - const SizedBox( - height: 4, - ), - PentryVisitsStatusMenu( - initialValue: widget.model.ppmVisitStatus, - onSelect: (status) { - if (status != null) { - widget.model.ppmVisitStatus = status; - } - }, - ), - const SizedBox( - height: 8, - ), - const ASubTitle("Timer"), - if (widget.enableValidate && widget.model?.timer?.endAt == null) - ASubTitle( - context.translation.requiredWord, - color: Colors.red, - ), - const SizedBox( - height: 4, - ), - AppTimer( - timer: widget.model.timer, - enabled: widget.model.timer.endAt == null, - onChange: (timer) async { - widget.model.timer = timer; - return true; - }, - ), - const SizedBox( - height: 8, - ), - const ASubTitle("Status"), - if (widget.enableValidate && widget.model.status == null) - ASubTitle( - context.translation.requiredWord, - color: Colors.red, - ), - const SizedBox( - height: 4, - ), - PentryStatusMenu( - initialValue: widget.model.status, - onSelect: (status) { - widget.model.status = status; - }, - ), - const SizedBox( - height: 8, - ), - const ASubTitle("Actual Visit Date"), - if (widget.enableValidate && widget.model.actualVisitDate == null) - ASubTitle( - context.translation.requiredWord, - color: Colors.red, - ), - const SizedBox( - height: 4, - ), - ADatePicker( - date: widget.model.actualVisitDate, - from: DateTime.now().subtract(const Duration(days: 30)), - onDatePicker: (date) { - if (date == null) return; - widget.model.actualVisitDate = date; - setState(() {}); - }, - ), - const SizedBox( - height: 8, - ), - const ASubTitle("Expected Visit Date"), - if (widget.enableValidate && widget.model.expectedVisitDate == null) - ASubTitle( - context.translation.requiredWord, - color: Colors.red, - ), - const SizedBox( - height: 4, - ), - ADatePicker( - date: widget.model.expectedVisitDate, - from: DateTime.now().subtract(const Duration(days: 30)), - onDatePicker: (date) { - if (date == null) return; - widget.model.expectedVisitDate = date; - setState(() {}); - }, - ), - const SizedBox( - height: 8, - ), - const ASubTitle("Traveling Hours"), - const SizedBox( - height: 4, - ), - ATextFormField( - initialValue: (widget.model.travelingHours ?? "").toString(), - textAlign: TextAlign.center, - style: Theme.of(context).textTheme.titleMedium, - textInputType: TextInputType.number, - onChange: (value) { - widget.model.travelingHours = value; - }, - ), - const SizedBox(height: 12), - MultiFilesPicker(label: "PPM Attachments", files: widget.model.files), - // AMiniOneFilePicker( - // //error: _validate && _serviceReport.image == null, - // file: widget.model.file, - // onPick: (file) { - // widget.model.file = file; - // }, - // ), - const SizedBox( - height: 8, - ), - const ASubTitle("Nurse Signature"), - ESignature( - oldSignature: widget.model.signatureNurse, - newSignature: widget.model.localNurseSignature, - onChange: (signature) { - if (signature == null || signature.isEmpty) { - return; - } - widget.model.localNurseSignature = signature; - widget.model.signatureNurse = "${DateTime.now().toIso8601String()}.png|${base64Encode(signature)}"; - }, - ), - const SizedBox( - height: 8, - ), - const ASubTitle("Engineer Signature"), - ESignature( - oldSignature: widget.model.signatureEngineer, - newSignature: widget.model.localEngineerSignature, - onChange: (signature) { - if (signature == null || signature.isEmpty) { - return; - } - widget.model.localEngineerSignature = signature; - widget.model.signatureEngineer = "${DateTime.now().toIso8601String()}.png|${base64Encode(signature)}"; - }, - ), - const SizedBox( - height: 8, - ), - ], - ), - ), - ); - } -} diff --git a/lib/views/widgets/pentry/pentry_pm_kit_form.dart b/lib/views/widgets/pentry/pentry_pm_kit_form.dart index 72df9d7b..8236c7ca 100644 --- a/lib/views/widgets/pentry/pentry_pm_kit_form.dart +++ b/lib/views/widgets/pentry/pentry_pm_kit_form.dart @@ -1,12 +1,15 @@ import 'package:flutter/material.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/lookup.dart'; import 'package:test_sa/models/pantry/pm_kit.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/new_views/common_widgets/app_text_form_field.dart'; import 'package:test_sa/views/widgets/parts/auto_complete_parts_field.dart'; -import 'package:test_sa/views/widgets/titles/app_sub_title.dart'; + +import '../../../new_views/app_style/app_color.dart'; +import '../../../new_views/common_widgets/app_filled_button.dart'; class PentryPMKitForm extends StatefulWidget { final List models; @@ -27,18 +30,16 @@ class _PentryPMKitFormState extends State { @override Widget build(BuildContext context) { return ListView.builder( - padding: EdgeInsets.only( - top: 12 * AppStyle.getScaleFactor(context), - left: 12 * AppStyle.getScaleFactor(context), - right: 12 * AppStyle.getScaleFactor(context), - bottom: 100 * AppStyle.getScaleFactor(context) + MediaQuery.of(context).padding.bottom, - ), itemCount: widget.models.length + 1, shrinkWrap: true, + padding: EdgeInsets.only(top: 16.toScreenHeight), itemBuilder: (context, index) { if (index == widget.models.length) { - return AButton( - text: context.translation.add, + return AppFilledButton( + label: "Add Item", + maxWidth: true, + textColor: Colors.white, + buttonColor: context.isDark ? AppColor.neutral60 : AppColor.neutral50, onPressed: () { widget.models.add(PMKit()); setState(() {}); @@ -46,46 +47,49 @@ class _PentryPMKitFormState extends State { ); } final model = widget.models[index]; - return Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - ASubTitle("#${index + 1}"), - if (index != 0) - ASmallButton( - color: Theme.of(context).colorScheme.error, - text: context.translation.delete, - onPressed: () { - widget.models.remove(model); - setState(() {}); - }, - ), - ], - ), - const SizedBox( - height: 8, - ), - const ASubTitle("Item Code"), - const SizedBox( - height: 4, - ), - AutoCompletePartsField( - assetId: widget.assetId, - clearAfterPick: false, - initialValue: (model.itemCode?.name ?? "").toString(), - onPick: (part) { - model.itemCode = Lookup(id: part.id, name: part?.sparePart?.partNo); - }, - ), - const SizedBox( - height: 8, - ), - Divider( - color: Theme.of(context).textTheme.titleMedium.color, - ), - ], + final TextEditingController controller = TextEditingController(text: model.quantityNeeded); + return Container( + padding: const EdgeInsets.all(16), + margin: EdgeInsets.only(bottom: 16.toScreenHeight), + decoration: BoxDecoration( + color: Theme.of(context).cardColor, + borderRadius: BorderRadius.circular(20), + boxShadow: [BoxShadow(color: Colors.black.withOpacity(0.03), blurRadius: 14)], + ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + "Item ${index + 1}".heading5(context), + "trash".toSvgAsset(width: 15, height: 20).onPress(() { + widget.models.remove(model); + setState(() {}); + }), + ], + ), + 16.height, + AutoCompletePartsField( + assetId: widget.assetId, + clearAfterPick: false, + initialValue: (model.itemCode?.name ?? "").toString(), + onPick: (part) { + model.itemCode = Lookup(id: part.id, name: part?.sparePart?.partNo); + model.itemName = part?.sparePart?.partName; + }, + ), + 8.height, + AppTextFormField( + controller: controller, + labelText: context.translation.quantity, + textInputType: TextInputType.number, + onChange: (text) { + model.quantityNeeded = num.tryParse(text ?? "")?.toString(); + }, + ), + ], + ), ); }, ); diff --git a/lib/views/widgets/pentry/pentry_ppm_check_list_form.dart b/lib/views/widgets/pentry/pentry_ppm_check_list_form.dart index 8d2c4866..0faa222f 100644 --- a/lib/views/widgets/pentry/pentry_ppm_check_list_form.dart +++ b/lib/views/widgets/pentry/pentry_ppm_check_list_form.dart @@ -1,135 +1,49 @@ import 'package:flutter/material.dart'; -import 'package:test_sa/controllers/localization/localization.dart'; import 'package:test_sa/extensions/context_extension.dart'; +import 'package:test_sa/extensions/int_extensions.dart'; +import 'package:test_sa/extensions/text_extensions.dart'; import 'package:test_sa/models/pantry/ppm_check_list.dart'; -import 'package:test_sa/views/app_style/sizing.dart'; -import 'package:test_sa/views/widgets/app_text_form_field.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/status/pentry/pentry_task_status_mune.dart'; -import 'package:test_sa/views/widgets/titles/app_sub_title.dart'; +import 'package:test_sa/new_views/app_style/app_color.dart'; +import 'package:test_sa/new_views/common_widgets/app_text_form_field.dart'; -class PentryPPMCheckListForm extends StatefulWidget { +class PentryPMChecklistForm extends StatefulWidget { final List models; final bool enableValidate; - const PentryPPMCheckListForm({ - Key key, - this.models, - this.enableValidate, - }) : super(key: key); + const PentryPMChecklistForm({Key key, this.models, this.enableValidate}) : super(key: key); @override - State createState() => _PentryPPMCheckListFormState(); + State createState() => _PentryPMChecklistFormState(); } -class _PentryPPMCheckListFormState extends State { +class _PentryPMChecklistFormState extends State { + PPMCheckList item = PPMCheckList(); @override Widget build(BuildContext context) { - return ListView.builder( - padding: EdgeInsets.only( - top: 12 * AppStyle.getScaleFactor(context), left: 12 * AppStyle.getScaleFactor(context), right: 12 * AppStyle.getScaleFactor(context), bottom: 80 * AppStyle.getScaleFactor(context)), - itemCount: widget.models.length + 1, - itemBuilder: (context, index) { - if (index == widget.models.length) { - return AButton( - text: context.translation.add, - onPressed: () { - widget.models.add(PPMCheckList()); - setState(() {}); - }, - ); - } - final model = widget.models[index]; - return ListView( - shrinkWrap: true, - physics: const ClampingScrollPhysics(), + padding: EdgeInsets.only(top: 16.toScreenHeight), + itemCount: widget.models.length, + shrinkWrap: true, + itemBuilder: (context, index) { + final model = widget.models[index]; + return Card( + child: ExpansionTile( + shape: const Border(), + title: (model.title ?? "").heading5(context), + subtitle: "Status ${model.status?.name}".bodyText(context), + initiallyExpanded: index == 0, + iconColor: AppColor.neutral50, + collapsedIconColor: AppColor.neutral50, + childrenPadding: EdgeInsets.symmetric(horizontal: 16.toScreenWidth, vertical: 8.toScreenHeight), children: [ - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - ASubTitle("#${index + 1}"), - if (index != 0) - ASmallButton( - color: Theme.of(context).colorScheme.error, - text: context.translation.delete, - onPressed: () { - widget.models.remove(model); - setState(() {}); - }, - ), - ], - ), - const SizedBox( - height: 8, - ), - const ASubTitle("Task"), - const SizedBox( - height: 4, - ), - ATextFormField( - initialValue: (model.title?.trim() ?? "").toString(), - textAlign: TextAlign.center, - style: Theme.of(context).textTheme.subtitle1, - textInputType: TextInputType.text, - onChange: (value) { - model.title = value; - }, - ), - const SizedBox( - height: 8, - ), - ASubTitle(context.translation.status), - const SizedBox( - height: 4, - ), - PentryTaskStatusMenu( - initialValue: model.status, - onSelect: (status) { - model.status = status; - }, - ), - const SizedBox( - height: 8, - ), - const ASubTitle("Comment"), - const SizedBox( - height: 4, - ), - ATextFormField( - initialValue: (model.comment ?? "").toString(), - textAlign: TextAlign.center, - style: Theme.of(context).textTheme.subtitle1, - textInputType: TextInputType.text, - onChange: (value) { - model.comment = value; - }, - ), - const SizedBox( - height: 8, - ), - const ASubTitle("Measured Value"), - const SizedBox( - height: 4, - ), - ATextFormField( - initialValue: (model.measuredValue ?? "").toString(), - textAlign: TextAlign.center, - style: Theme.of(context).textTheme.subtitle1, - textInputType: TextInputType.text, - onChange: (value) { - model.measuredValue = value; - }, - ), - const SizedBox( - height: 8, - ), - Divider( - color: Theme.of(context).textTheme.titleMedium.color, - ), + AppTextFormField(labelText: "Measured Value", initialValue: model.measuredValue, enable: false), + 8.height, + AppTextFormField(labelText: context.translation.comment, initialValue: model.comment, enable: false), + 8.height, ], - ); - }); + ), + ); + }, + ); } } diff --git a/lib/views/widgets/pentry/pentry_tbs_form.dart b/lib/views/widgets/pentry/pentry_tbs_form.dart new file mode 100644 index 00000000..b554b882 --- /dev/null +++ b/lib/views/widgets/pentry/pentry_tbs_form.dart @@ -0,0 +1,147 @@ +import 'dart:convert'; + +import 'package:flutter/material.dart'; +import 'package:test_sa/extensions/context_extension.dart'; +import 'package:test_sa/extensions/int_extensions.dart'; +import 'package:test_sa/models/lookup.dart'; +import 'package:test_sa/models/pantry/pentry.dart'; +import 'package:test_sa/new_views/common_widgets/single_item_drop_down_menu.dart'; +import 'package:test_sa/providers/ppm_device_status_provider.dart'; +import 'package:test_sa/providers/ppm_visit_status_provider.dart'; +import 'package:test_sa/views/widgets/e_signature/e_signature.dart'; +import 'package:test_sa/views/widgets/timer/app_timer.dart'; + +import '../date_and_time/date_picker.dart'; +import '../images/multi_image_picker.dart'; + +class PentryTBSForm extends StatefulWidget { + final Pentry model; + final bool enableValidate; + + const PentryTBSForm({ + Key key, + this.model, + this.enableValidate, + }) : super(key: key); + + @override + State createState() => _PentryTBSFormState(); +} + +class _PentryTBSFormState extends State { + @override + Widget build(BuildContext context) { + widget.model?.files ??= []; + + return SingleChildScrollView( + child: Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + 8.height, + SingleItemDropDownMenu( + context: context, + initialValue: widget.model.ppmVisitStatus, + title: "PPM Visit Status", + onSelect: (value) { + if (value != null) { + widget.model.ppmVisitStatus = value; + } + }, + ), + 8.height, + AppTimer( + timer: widget.model.timer, + enabled: widget.model.timer.endAt == null, + onChange: (timer) async { + widget.model.timer = timer; + return true; + }, + ), + 8.height, + SingleItemDropDownMenu( + context: context, + initialValue: widget.model.status, + title: "Device Status", + onSelect: (value) { + if (value != null) { + widget.model.status = value; + } + }, + ), + 8.height, + ADatePicker( + label: "Actual Visit Date", + date: widget.model.actualVisitDate, + from: DateTime.now().subtract(const Duration(days: 30)), + onDatePicker: (date) { + if (date == null) return; + widget.model.actualVisitDate = date; + setState(() {}); + }, + ), + 8.height, + ADatePicker( + label: "Expected Visit Date", + date: widget.model.expectedVisitDate, + from: DateTime.now().subtract(const Duration(days: 30)), + onDatePicker: (date) { + if (date == null) return; + widget.model.expectedVisitDate = date; + setState(() {}); + }, + ), + 8.height, + // const ASubTitle("Traveling Hours"), + // const SizedBox( + // height: 4, + // ), + // ATextFormField( + // initialValue: (widget.model.travelingHours ?? "").toString(), + // textAlign: TextAlign.center, + // style: Theme.of(context).textTheme.titleMedium, + // textInputType: TextInputType.number, + // onChange: (value) { + // widget.model.travelingHours = value; + // }, + // ), + 8.height, + MultiFilesPicker(label: "Attach Image", files: widget.model.files), + // AMiniOneFilePicker( + // //error: _validate && _serviceReport.image == null, + // file: widget.model.file, + // onPick: (file) { + // widget.model.file = file; + // }, + // ), + 8.height, + ESignature( + title: "Nurse Signature", + oldSignature: widget.model.signatureNurse, + newSignature: widget.model.localNurseSignature, + onChange: (signature) { + // if (signature == null || signature.isEmpty) { + // return; + // } + widget.model.localNurseSignature = signature; + widget.model.signatureNurse = "${DateTime.now().toIso8601String()}.png|${base64Encode(signature)}"; + }, + ), + 8.height, + ESignature( + title: context.translation.engSign, + oldSignature: widget.model.signatureEngineer, + newSignature: widget.model.localEngineerSignature, + onChange: (signature) { + // if (signature == null || signature.isEmpty) { + // return; + // } + widget.model.localEngineerSignature = signature; + widget.model.signatureEngineer = "${DateTime.now().toIso8601String()}.png|${base64Encode(signature)}"; + }, + ), + 8.height, + ], + ), + ); + } +} diff --git a/lib/views/widgets/timer/app_timer.dart b/lib/views/widgets/timer/app_timer.dart index fdfe2483..b7bbbcc1 100644 --- a/lib/views/widgets/timer/app_timer.dart +++ b/lib/views/widgets/timer/app_timer.dart @@ -1,10 +1,14 @@ import 'dart:async'; import 'package:flutter/material.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/timer_model.dart'; -import 'package:test_sa/views/app_style/colors.dart'; import 'package:test_sa/views/app_style/sizing.dart'; +import '../../../new_views/app_style/app_color.dart'; + class AppTimer extends StatefulWidget { final TimerModel timer; final Future Function(TimerModel) onChange; @@ -96,37 +100,37 @@ class _AppTimerState extends State { @override Widget build(BuildContext context) { - return SizedBox( + return Container( 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 || widget.enabled == false ? null : _onPressed, - child: _loading - ? const SizedBox.square( - dimension: 18, - child: CircularProgressIndicator( - color: Colors.white, - )) - : Row( - children: [ - if (widget.enabled) Icon(_running ? Icons.pause : Icons.play_arrow), - Expanded( - child: Center( - child: ValueListenableBuilder( - valueListenable: _period, - builder: (context, value, _) { - return Text( - value, - style: widget.enabled ? widget.style : widget.style?.copyWith(color: Colors.black54), - ); - }), - ), - ), - ], - ), + height: 56.toScreenHeight, + padding: EdgeInsets.symmetric(horizontal: 16.toScreenWidth), + decoration: BoxDecoration( + color: Theme.of(context).cardColor, + borderRadius: BorderRadius.circular(10), + boxShadow: [BoxShadow(color: Colors.black.withOpacity(0.05), blurRadius: 10)], ), - ); + child: _loading + ? const SizedBox.square(dimension: 18, child: CircularProgressIndicator(color: Colors.white)) + : Row( + children: [ + Expanded( + child: ValueListenableBuilder( + valueListenable: _period, + builder: (context, value, _) { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + "Timer".tinyFont(context), + value.bodyText(context).custom(color: AppColor.neutral50), + ], + ); + }, + ), + ), + if (widget.enabled) Icon(_running ? Icons.pause : Icons.play_arrow), + ], + ), + ).onPress(_loading || widget.enabled == false ? () {} : _onPressed); } } diff --git a/lib/views/widgets/visits/visit_item.dart b/lib/views/widgets/visits/visit_item.dart index b4546039..b88e8809 100644 --- a/lib/views/widgets/visits/visit_item.dart +++ b/lib/views/widgets/visits/visit_item.dart @@ -1,171 +1,100 @@ import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; -import 'package:test_sa/controllers/localization/localization.dart'; -import 'package:test_sa/controllers/providers/api/user_provider.dart'; import 'package:test_sa/extensions/context_extension.dart'; +import 'package:test_sa/extensions/int_extensions.dart'; +import 'package:test_sa/extensions/string_extensions.dart'; +import 'package:test_sa/extensions/widget_extensions.dart'; import 'package:test_sa/models/enums/user_types.dart'; -import 'package:test_sa/models/subtitle.dart'; import 'package:test_sa/models/visits/visit.dart'; -import 'package:test_sa/views/app_style/sizing.dart'; -import 'package:test_sa/views/widgets/visits/visit_status.dart'; +import 'package:test_sa/views/pages/user/visits/visit_details.dart'; + +import '../../../controllers/providers/api/user_provider.dart'; +import '../../../extensions/text_extensions.dart'; +import '../../app_style/colors.dart'; +import '../../pages/user/visits/pantry/edit_pentry.dart'; +import '../requests/request_status.dart'; class VisitItem extends StatelessWidget { final Visit visit; - final int index; - final bool isSelected; - final bool activeSelectMod; - final Function(Visit) onPressed; - final Function(Visit) onLongPress; - final Function(Visit) onSelect; - const VisitItem({Key key, this.visit, this.onPressed, this.isSelected = false, this.activeSelectMod = false, this.onLongPress, this.onSelect, this.index}) : super(key: key); + const VisitItem({Key key, this.visit}) : super(key: key); @override Widget build(BuildContext context) { UserProvider userProvider = Provider.of(context); - 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: const EdgeInsets.symmetric(vertical: 8, horizontal: 8), - backgroundColor: itemColor, - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(AppStyle.getBorderRadius(context)), - ), - ), - onPressed: () { - if (activeSelectMod && userProvider.user.type == UsersTypes.engineer) { - onSelect(visit); - } else { - onPressed(visit); - } - }, - onLongPress: userProvider.user.type == UsersTypes.engineer - ? () { - onLongPress(visit); - } - : null, - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Row( - children: [ - Expanded( - child: Text( - "S.N: ${visit.deviceSerialNumber}" ?? "No serial number", - style: Theme.of(context).textTheme.titleLarge.copyWith(color: onItemColor, fontSize: 16, fontWeight: FontWeight.bold), - ), - ), - AnimatedSwitcher( - duration: const Duration(milliseconds: 400), - child: Visibility( - key: ValueKey(activeSelectMod), - visible: activeSelectMod, - child: SizedBox( - height: 18, - child: Checkbox( - activeColor: Colors.black38, - value: isSelected, - onChanged: (value) { - onSelect(visit); - }), - ), - ), - ), - VisitStatusLabel( - visit: visit, - ) - ], - ), - Divider( - color: onItemColor, - ), - Text( - visit.deviceNumber ?? "", - style: Theme.of(context).textTheme.titleMedium.copyWith(color: onItemColor, fontSize: 14), - ), - Divider( - color: onItemColor, - ), - Row( - children: [ - Expanded( - child: Text( - visit.hospitalName ?? "No client found", - style: Theme.of(context).textTheme.titleMedium.copyWith( - color: onItemColor, - fontSize: 14, - ), - ), - ), - ], - ), - Text( - visit.modelAndBrand ?? "", - style: Theme.of(context).textTheme.titleMedium.copyWith( - color: onItemColor, - fontSize: 14, - ), - ), - if (visit.employName != null && visit.employName.isNotEmpty) Divider(color: onItemColor), - if (visit.employName != null && visit.employName.isNotEmpty) + return Container( + decoration: ShapeDecoration( + color: Colors.white, + shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(20)), + shadows: const [BoxShadow(color: Color(0x07000000), blurRadius: 14, offset: Offset(0, 0), spreadRadius: 0)], + ), + padding: const EdgeInsets.all(16), + margin: EdgeInsets.only(bottom: 8.toScreenHeight), + child: Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ Row( children: [ - Expanded( - child: Text( - visit.employName ?? "No employ found", - style: Theme.of(context).textTheme.titleLarge.copyWith(color: onItemColor, fontSize: 14, fontWeight: FontWeight.bold), - ), + // StatusLabel( + // label: visit.priority.name, + // id: visit.priority.id, + // textColor: AColors.getPriorityStatusTextColor(visit.priority.id), + // backgroundColor: AColors.getPriorityStatusColor(visit.priority.id)), + // 8.width, + StatusLabel( + label: visit.status.name, + id: visit.status.id, + textColor: AColors.getRequestStatusTextColor(visit.status.value), + backgroundColor: AColors.getRequestStatusColor(visit.status.value), ), - // Text( - // visit.contactStatus ?? "", - // style: Theme.of(context).textTheme.subtitle1.copyWith( - // color: onItemColor, - // fontSize: 14, - // ), - // ), + 1.width.expanded, ], ), - Divider( - color: onItemColor, - ), - Row( - children: [ - Expanded( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - context.translation.expectDate, - style: Theme.of(context).textTheme.titleLarge.copyWith(color: onItemColor, fontSize: 14), - ), - Text( - visit.expectDate ?? context.translation.noDateFound, - style: Theme.of(context).textTheme.titleLarge.copyWith(color: onItemColor, fontSize: 14), - ), - ], + 8.height, + Text(visit.deviceEnglishName, style: AppTextStyles.heading5.copyWith(color: const Color(0xFF3B3D4A))), + 8.height, + Text( + '${context.translation.assetNumber}: ${visit.deviceNumber}', + style: AppTextStyles.bodyText.copyWith(color: const Color(0xFF757575)), + ), + Text( + 'Asset Serial No.: ${visit.deviceSerialNumber}', + style: AppTextStyles.bodyText.copyWith(color: const Color(0xFF757575)), + ), + Text( + 'Code: ${visit.serialNumber}', + style: AppTextStyles.bodyText.copyWith(color: const Color(0xFF757575)), + ), + 16.height, + Row( + mainAxisSize: MainAxisSize.min, + children: [ + Text( + 'View Details', + style: AppTextStyles.bodyText.copyWith(color: const Color(0xFF4A8DB7)), ), - ), - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - context.translation.actualDate, - style: Theme.of(context).textTheme.titleLarge.copyWith(color: onItemColor, fontSize: 14), - ), - Text( - visit.actualDate ?? context.translation.noDateFound, - style: Theme.of(context).textTheme.titleLarge.copyWith(color: onItemColor, fontSize: 14), - ), - ], - ), - ], - ), - ], - ), + 4.width, + const Icon(Icons.arrow_forward, color: Color(0xFF4A8DB7), size: 14) + ], + ).onPress(() { + Navigator.of(context).push(MaterialPageRoute(builder: (_) => VisitDetailsPage(visit: visit))); + }), + ], + ).expanded, + 8.width, + Column( + children: [ + if (userProvider.user.type == UsersTypes.engineer && visit.status.value != 5 && visit.status.value != 3) + "edit".toSvgAsset(height: 48, width: 48).onPress(() { + Navigator.of(context).push(MaterialPageRoute(builder: (_) => EditPentry(visit: visit, pentry: visit.pentry))); + }), + Text(visit.createdOn != null ? visit.createdOn.toServiceRequestCardFormat : "", textAlign: TextAlign.end, style: AppTextStyles.tinyFont.copyWith(color: const Color(0xFF3B3D4A))), + ], + ) + ], ), ); } diff --git a/lib/views/widgets/visits/visits_list.dart b/lib/views/widgets/visits/visits_list.dart index 0fd150be..5fe65349 100644 --- a/lib/views/widgets/visits/visits_list.dart +++ b/lib/views/widgets/visits/visits_list.dart @@ -1,14 +1,13 @@ import 'package:flutter/material.dart'; -import 'package:test_sa/controllers/localization/localization.dart'; +import 'package:provider/provider.dart'; import 'package:test_sa/extensions/context_extension.dart'; -import 'package:test_sa/models/subtitle.dart'; import 'package:test_sa/models/visits/visit.dart'; -import 'package:test_sa/views/app_style/sizing.dart'; -import 'package:test_sa/views/pages/user/visits/visit_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/visits/visit_item.dart'; +import '../../../controllers/providers/api/user_provider.dart'; + class VisitsList extends StatefulWidget { final List visits; final bool nextPage; @@ -32,10 +31,9 @@ class _VisitsListState extends State { @override Widget build(BuildContext context) { + UserProvider userProvider = Provider.of(context); if (widget.visits.isEmpty) { - return NoItemFound( - message: context.translation.noVisitsFound, - ); + return NoItemFound(message: context.translation.noVisitsFound); } return Stack( children: [ @@ -43,81 +41,54 @@ class _VisitsListState extends State { nextPage: widget.nextPage, onLazyLoad: widget.onLazyLoad, child: ListView.builder( - //physics: BouncingScrollPhysics(), - itemCount: widget.visits.length, - padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8), - itemBuilder: (context, itemIndex) { - Visit visit = widget.visits[itemIndex]; - bool isSelected = _selectedVisits.contains(visit); - return VisitItem( - visit: visit, - isSelected: isSelected, - index: itemIndex, - activeSelectMod: _selectedVisits.isNotEmpty, - onPressed: (visit) { - Navigator.of(context).push(MaterialPageRoute( - builder: (_) => VisitDetailsPage( - visit: visit, - ))); - }, - onSelect: (visit) { - if (isSelected) { - _selectedVisits.remove(visit); - } else { - _selectedVisits.add(visit); - } - setState(() {}); - }, - onLongPress: (visit) { - if (isSelected) { - _selectedVisits.remove(visit); - } else { - _selectedVisits.add(visit); - } - setState(() {}); - }, - ); - }), - ), - Align( - alignment: Alignment.bottomLeft, - child: Padding( - padding: EdgeInsets.all(8.0 * AppStyle.getScaleFactor(context)), - child: AnimatedSwitcher( - duration: const Duration(milliseconds: 400), - child: Visibility( - key: ValueKey(_selectedVisits.isNotEmpty), - visible: _selectedVisits.isNotEmpty, - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - FloatingActionButton( - heroTag: "cancel", - child: const Icon(Icons.cancel), - onPressed: () { - _selectedVisits.clear(); - setState(() {}); - }, - ), - FloatingActionButton( - heroTag: "edit", - child: const Icon(Icons.edit), - onPressed: () { - if (!widget.visits.contains(_selectedVisits.first)) { - _selectedVisits.clear(); - setState(() {}); - return; - } - widget.onEditGroup(_selectedVisits); - //_selectedVisits.clear(); - }, - ), - ], - ), - ), - ), + itemCount: widget.visits.length, + padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8), + itemBuilder: (context, itemIndex) { + Visit visit = widget.visits[itemIndex]; + // bool isSelected = _selectedVisits.contains(visit); + return VisitItem(visit: visit); + }, ), - ) + ), + // Align( + // alignment: Alignment.bottomLeft, + // child: Padding( + // padding: EdgeInsets.all(8.0 * AppStyle.getScaleFactor(context)), + // child: AnimatedSwitcher( + // duration: const Duration(milliseconds: 400), + // child: Visibility( + // key: ValueKey(_selectedVisits.isNotEmpty), + // visible: _selectedVisits.isNotEmpty, + // child: Row( + // mainAxisAlignment: MainAxisAlignment.spaceBetween, + // children: [ + // FloatingActionButton( + // heroTag: "cancel", + // child: const Icon(Icons.cancel), + // onPressed: () { + // _selectedVisits.clear(); + // setState(() {}); + // }, + // ), + // FloatingActionButton( + // heroTag: "edit", + // child: const Icon(Icons.edit), + // onPressed: () { + // if (!widget.visits.contains(_selectedVisits.first)) { + // _selectedVisits.clear(); + // setState(() {}); + // return; + // } + // widget.onEditGroup(_selectedVisits); + // //_selectedVisits.clear(); + // }, + // ), + // ], + // ), + // ), + // ), + // ), + // ) ], ); }