From d13bfa5f60596a6688696d8154ea19d78cbc8251 Mon Sep 17 00:00:00 2001 From: zaid_daoud Date: Mon, 19 Jun 2023 09:38:16 +0300 Subject: [PATCH 1/3] Wo Details Bottom Sheet & Spare Parts Bottom Sheet Design Done [without activating update buttons] --- lib/main.dart | 6 +- .../create_sub_workorder_page.dart | 120 ++++++++++++ ...ge.dart => search_sub_workorder_page.dart} | 12 +- .../spare_parts_details_bottom_sheet.dart | 130 +++++++++++++ .../work_order_details_bottom_sheet.dart | 181 ++++++++++++++++++ lib/views/pages/user/land_page.dart | 4 +- 6 files changed, 443 insertions(+), 10 deletions(-) create mode 100644 lib/views/pages/sub_workorder/create_sub_workorder_page.dart rename lib/views/pages/sub_workorder/{sub_workorder_page.dart => search_sub_workorder_page.dart} (95%) create mode 100644 lib/views/pages/sub_workorder/spare_parts_details_bottom_sheet.dart create mode 100644 lib/views/pages/sub_workorder/work_order_details_bottom_sheet.dart diff --git a/lib/main.dart b/lib/main.dart index c6ffff50..89f7489a 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -36,7 +36,8 @@ import 'package:test_sa/views/app_style/colors.dart'; import 'package:test_sa/views/pages/login.dart'; import 'package:test_sa/views/pages/register.dart'; import 'package:test_sa/views/pages/splash_screen.dart'; -import 'package:test_sa/views/pages/sub_workorder/sub_workorder_page.dart'; +import 'package:test_sa/views/pages/sub_workorder/create_sub_workorder_page.dart'; +import 'package:test_sa/views/pages/sub_workorder/search_sub_workorder_page.dart'; import 'package:test_sa/views/pages/user/gas_refill/request_gas_refill.dart'; import 'package:test_sa/views/pages/user/gas_refill/track_gas_refill.dart'; import 'package:test_sa/views/pages/user/land_page.dart'; @@ -179,7 +180,8 @@ class MyApp extends StatelessWidget { TrackGasRefillPage.id: (_) => const TrackGasRefillPage(), RequestDeviceTransfer.id: (_) => const RequestDeviceTransfer(), TrackDeviceTransferPage.id: (_) => const TrackDeviceTransferPage(), - SubWorkOrderPage.id: (_) => const SubWorkOrderPage(), + SearchSubWorkOrderPage.id: (_) => const SearchSubWorkOrderPage(), + CreateSubWorkOrderPage.id: (_) => const CreateSubWorkOrderPage(), }, ), ), diff --git a/lib/views/pages/sub_workorder/create_sub_workorder_page.dart b/lib/views/pages/sub_workorder/create_sub_workorder_page.dart new file mode 100644 index 00000000..a0a8889f --- /dev/null +++ b/lib/views/pages/sub_workorder/create_sub_workorder_page.dart @@ -0,0 +1,120 @@ +import 'package:flutter/material.dart'; +import 'package:test_sa/views/app_style/colors.dart'; +import 'package:test_sa/views/pages/sub_workorder/spare_parts_details_bottom_sheet.dart'; +import 'package:test_sa/views/pages/sub_workorder/work_order_details_bottom_sheet.dart'; + +import '../../../controllers/localization/localization.dart'; +import '../../../models/subtitle.dart'; +import '../../widgets/buttons/app_back_button.dart'; +import '../../widgets/buttons/app_button.dart'; + +class CreateSubWorkOrderPage extends StatelessWidget { + static const id = "/CreateSubWorkOrder"; + const CreateSubWorkOrderPage({Key key}) : super(key: key); + + @override + Widget build(BuildContext context) { + final Subtitle subtitle = AppLocalization.of(context).subtitle; + return Scaffold( + body: SafeArea( + child: SingleChildScrollView( + child: Column( + children: [ + Container( + color: AColors.primaryColor, + padding: const EdgeInsets.symmetric(horizontal: 0, vertical: 4), + child: Column( + children: [ + Row( + children: [ + const ABackButton(), + Expanded( + child: Center( + child: Text( + "New Work Order", + style: Theme.of(context).textTheme.headline6.copyWith(color: AColors.white, fontStyle: FontStyle.italic), + ), + ), + ), + const SizedBox( + width: 48, + ) + ], + ), + ], + ), + ), + Padding( + padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 16), + child: Column( + children: [ + const SizedBox(height: 8), + InkWell( + onTap: () { + showModalBottomSheet( + context: context, + useSafeArea: true, + isScrollControlled: true, + backgroundColor: Colors.transparent, + builder: (context) => const WorkOrderDetailsBottomSheet(), + ); + }, + child: Card( + child: ListTile( + title: Row( + children: [ + Text( + "WO Details", + style: Theme.of(context).textTheme.bodyMedium, + ), + const Text("*", style: TextStyle(color: Colors.red)), + ], + ), + trailing: const Icon(Icons.arrow_forward_ios, size: 14, color: AColors.primaryColor), + ), + ), + ), + const SizedBox(height: 8), + InkWell( + onTap: () { + showModalBottomSheet( + context: context, + useSafeArea: true, + isScrollControlled: true, + backgroundColor: Colors.transparent, + builder: (context) => const SparePartsBottomSheet(), + ); + }, + child: Card( + child: ListTile( + title: Row( + children: [ + Text( + "Spare Parts", + style: Theme.of(context).textTheme.bodyMedium, + ), + const Text("*", style: TextStyle(color: Colors.red)), + ], + ), + trailing: const Icon(Icons.arrow_forward_ios, size: 14, color: AColors.primaryColor), + ), + ), + ), + ], + ), + ), + ], + ), + ), + ), + floatingActionButtonLocation: FloatingActionButtonLocation.centerDocked, + floatingActionButton: Padding( + padding: const EdgeInsets.all(16.0), + child: AButton( + text: subtitle.update, + onPressed: () {}, + ), + ), + ); + } +} diff --git a/lib/views/pages/sub_workorder/sub_workorder_page.dart b/lib/views/pages/sub_workorder/search_sub_workorder_page.dart similarity index 95% rename from lib/views/pages/sub_workorder/sub_workorder_page.dart rename to lib/views/pages/sub_workorder/search_sub_workorder_page.dart index 4aeaa1be..e7747ace 100644 --- a/lib/views/pages/sub_workorder/sub_workorder_page.dart +++ b/lib/views/pages/sub_workorder/search_sub_workorder_page.dart @@ -1,7 +1,6 @@ import 'package:flutter/material.dart'; import 'package:fluttertoast/fluttertoast.dart'; import 'package:provider/provider.dart'; -import 'package:test_sa/controllers/providers/api/service_requests_provider.dart'; import 'package:test_sa/models/engineer.dart'; import 'package:test_sa/models/lookup.dart'; import 'package:test_sa/models/service_request/search_work_order.dart'; @@ -11,6 +10,7 @@ import 'package:test_sa/views/widgets/date_and_time/date_picker.dart'; import '../../../controllers/api_routes/http_status_manger.dart'; import '../../../controllers/localization/localization.dart'; +import '../../../controllers/providers/api/service_requests_provider.dart'; import '../../app_style/colors.dart'; import '../../widgets/buttons/app_back_button.dart'; import '../../widgets/buttons/app_button.dart'; @@ -20,15 +20,15 @@ import '../../widgets/status/report/service_report_maintenance_situation.dart'; import '../../widgets/status/report/service_report_visit_date_operator.dart'; import '../../widgets/titles/app_sub_title.dart'; -class SubWorkOrderPage extends StatefulWidget { +class SearchSubWorkOrderPage extends StatefulWidget { static String id = "/SubWorkOrderPage"; - const SubWorkOrderPage({Key key}) : super(key: key); + const SearchSubWorkOrderPage({Key key}) : super(key: key); @override - State createState() => _SubWorkOrderPageState(); + State createState() => _SearchSubWorkOrderPageState(); } -class _SubWorkOrderPageState extends State { +class _SearchSubWorkOrderPageState extends State { final GlobalKey _formKey = GlobalKey(); final SearchWorkOrders _searchWorkOrders = SearchWorkOrders(); Subtitle _subtitle; @@ -55,7 +55,7 @@ class _SubWorkOrderPageState extends State { child: Center( child: Text( "Search Work Order", - style: Theme.of(context).textTheme.headline6.copyWith(color: AColors.white, fontStyle: FontStyle.italic), + style: Theme.of(context).textTheme.titleLarge.copyWith(color: AColors.white, fontStyle: FontStyle.italic), ), ), ), diff --git a/lib/views/pages/sub_workorder/spare_parts_details_bottom_sheet.dart b/lib/views/pages/sub_workorder/spare_parts_details_bottom_sheet.dart new file mode 100644 index 00000000..0af019bf --- /dev/null +++ b/lib/views/pages/sub_workorder/spare_parts_details_bottom_sheet.dart @@ -0,0 +1,130 @@ +import 'package:flutter/material.dart'; +import 'package:test_sa/views/app_style/colors.dart'; + +import '../../../controllers/localization/localization.dart'; +import '../../../models/subtitle.dart'; +import '../../widgets/app_text_form_field.dart'; +import '../../widgets/buttons/app_button.dart'; +import '../../widgets/titles/app_sub_title.dart'; + +class SparePartsBottomSheet extends StatefulWidget { + const SparePartsBottomSheet({Key key}) : super(key: key); + + @override + State createState() => _SparePartsBottomSheetState(); +} + +class _SparePartsBottomSheetState extends State { + final GlobalKey _formKey = GlobalKey(); + @override + Widget build(BuildContext context) { + final size = MediaQuery.of(context).size; + final Subtitle subtitle = AppLocalization.of(context).subtitle; + return Padding( + padding: EdgeInsets.only(bottom: MediaQuery.of(context).viewInsets.bottom), + child: ClipRRect( + borderRadius: const BorderRadius.only( + topLeft: Radius.circular(15), + topRight: Radius.circular(15), + ), + clipBehavior: Clip.antiAliasWithSaveLayer, + child: Container( + color: Colors.white, + height: size.height * 0.9, + padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 20), + child: Form( + key: _formKey, + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + const ASubTitle("Spare Parts"), + const SizedBox(height: 8), + Expanded( + child: Padding( + padding: const EdgeInsets.all(8.0), + child: SingleChildScrollView( + child: SingleChildScrollView( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + const SizedBox(height: 8), + ListView.builder( + itemCount: 1, + shrinkWrap: true, + physics: const NeverScrollableScrollPhysics(), + itemBuilder: (context, index) => Column( + children: [ + const ATextFormField(labelText: "Part No."), + const SizedBox(height: 8), + const ATextFormField( + labelText: "Description", + hintText: "Add Some Text", + textInputType: TextInputType.multiline, + ), + const SizedBox(height: 8), + const ATextFormField( + labelText: "Quantity", + textInputType: TextInputType.number, + ), + const SizedBox(height: 8), + InkWell( + onTap: () {}, + child: Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + const Icon(Icons.delete, color: Colors.red), + Text( + "Remove this part", + style: Theme.of(context).textTheme.bodySmall, + ), + ], + ), + ), + const SizedBox(height: 8), + ], + ), + ), + const Divider(), + const SizedBox(height: 8), + InkWell( + onTap: () {}, + child: Container( + decoration: BoxDecoration( + color: AColors.primaryColor.withOpacity(0.15), + borderRadius: BorderRadius.circular(10), + border: Border.all(color: AColors.primaryColor), + ), + child: ListTile( + title: Text( + "Add Part", + style: Theme.of(context).textTheme.bodyMedium?.copyWith( + color: AColors.primaryColor, + ), + ), + trailing: const Icon( + Icons.add_circle, + color: AColors.primaryColor, + size: 20, + ), + ), + ), + ), + const SizedBox(height: 24), + ], + ), + ), + ), + ), + ), + AButton( + text: subtitle.update, + onPressed: () {}, + ), + ], + ), + ), + ), + ), + ); + } +} diff --git a/lib/views/pages/sub_workorder/work_order_details_bottom_sheet.dart b/lib/views/pages/sub_workorder/work_order_details_bottom_sheet.dart new file mode 100644 index 00000000..718f4348 --- /dev/null +++ b/lib/views/pages/sub_workorder/work_order_details_bottom_sheet.dart @@ -0,0 +1,181 @@ +import 'package:flutter/material.dart'; +import 'package:test_sa/models/subtitle.dart'; +import 'package:test_sa/views/widgets/app_text_form_field.dart'; +import 'package:test_sa/views/widgets/buttons/app_button.dart'; +import 'package:test_sa/views/widgets/status/report/service_report_maintenance_situation.dart'; +import 'package:test_sa/views/widgets/status/report/service_report_repair_location.dart'; + +import '../../../controllers/localization/localization.dart'; +import '../../app_style/sizing.dart'; +import '../../widgets/date_and_time/time_picker.dart'; +import '../../widgets/status/report/service_report_all_users.dart'; +import '../../widgets/titles/app_sub_title.dart'; + +class WorkOrderDetailsBottomSheet extends StatefulWidget { + const WorkOrderDetailsBottomSheet({Key key}) : super(key: key); + + @override + State createState() => _WorkOrderDetailsBottomSheetState(); +} + +class _WorkOrderDetailsBottomSheetState extends State { + final GlobalKey _formKey = GlobalKey(); + @override + Widget build(BuildContext context) { + final size = MediaQuery.of(context).size; + final Subtitle subtitle = AppLocalization.of(context).subtitle; + return Padding( + padding: EdgeInsets.only(bottom: MediaQuery.of(context).viewInsets.bottom), + child: ClipRRect( + borderRadius: const BorderRadius.only( + topLeft: Radius.circular(15), + topRight: Radius.circular(15), + ), + clipBehavior: Clip.antiAliasWithSaveLayer, + child: Container( + color: Colors.white, + height: size.height * 0.9, + padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 20), + child: Form( + key: _formKey, + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + const ASubTitle("WO Details"), + const SizedBox(height: 8), + Expanded( + child: Padding( + padding: const EdgeInsets.all(8.0), + child: SingleChildScrollView( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + const SizedBox(height: 8), + const ATextFormField(enable: false, hintText: "Assigned Employee: ${123}"), + const SizedBox(height: 8), + const ASubTitle("Assistant Employee"), + const SizedBox(height: 4), + ServiceReportAllUsers( + // initialValue: _searchWorkOrders.assignedEmployee == null ? null : Engineer(id: _searchWorkOrders.assignedEmployee.id, name: _searchWorkOrders.assignedEmployee.name), + onSelect: (engineer) { + // _searchWorkOrders.assignedEmployee = AssignedEmployee(id: engineer.id, name: engineer.name); + }, + ), + const SizedBox(height: 8), + Row( + children: [ + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + const ASubTitle("Start of Work"), + SizedBox( + height: 8 * AppStyle.getScaleFactor(context), + ), + ADateTimePicker( + // date: _gasRefillProvider.startDate, + from: DateTime.now().subtract(const Duration(days: 365)), + to: DateTime.now().add(const Duration(days: 365)), + onDateTimePicker: (date) { + // _gasRefillProvider.startDate = date; + // setState(() {}); + }, + ), + ], + ), + ), + const SizedBox(width: 8), + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + const ASubTitle("End of Work"), + SizedBox( + height: 8 * AppStyle.getScaleFactor(context), + ), + ADateTimePicker( + // date: _gasRefillProvider.endDate, + from: DateTime.now().subtract(const Duration(days: 365)), + to: DateTime.now().add(const Duration(days: 365)), + onDateTimePicker: (date) { + // _gasRefillProvider.endDate = date; + // setState(() {}); + }, + ), + ], + ), + ), + ], + ), + const SizedBox(height: 8), + ASubTitle(subtitle.workingHours), + const SizedBox(height: 4), + ATextFormField( + initialValue: null, + textAlign: TextAlign.center, + // hintText: _gasRefillProvider.startDate == null + // ? "0" + // : ((_gasRefillProvider.endDate?.difference(_gasRefillProvider.startDate)?.inMinutes ?? 0) / 60)?.toStringAsFixed(2)?.toString() ?? "0", + enable: false, + style: Theme.of(context).textTheme.subtitle1, + // validator: (value) => Validator.isNumeric(value) ? null : _subtitle.requiredWord, + textInputType: TextInputType.number, + onSaved: (value) { + // _serviceReport.workHours = value; + }, + ), + const SizedBox(height: 8), + const ATextFormField( + labelText: "Travel Hours", + ), + const SizedBox(height: 8), + const ATextFormField( + labelText: "Travel Expense", + ), + const SizedBox(height: 8), + ASubTitle(subtitle.callLastSituation), + const SizedBox(height: 4), + ServiceReportMaintenanceSituation( + initialValue: null /*_searchWorkOrders.calllastSituation*/, + onSelect: (status) { + // if (status?.value == 12 || _searchWorkOrders.calllastSituation?.value == 12) { + // _searchWorkOrders.calllastSituation = status; + // setState(() {}); + // } else { + // _searchWorkOrders.calllastSituation = status; + // } + }, + ), + const SizedBox(height: 8), + const ASubTitle("Repair Location"), + const SizedBox(height: 4), + ServiceReportRepairLocation( + // initialValue: _serviceReport.repairLocation, + onSelect: (status) { + // _serviceReport.repairLocation = status; + }, + ), + const SizedBox(height: 8), + const ATextFormField( + labelText: "Technical Comments", + hintText: "Add Some Text", + textInputType: TextInputType.multiline, + ), + const SizedBox(height: 24), + ], + ), + ), + ), + ), + AButton( + text: subtitle.update, + onPressed: () {}, + ), + ], + ), + ), + ), + ), + ); + } +} diff --git a/lib/views/pages/user/land_page.dart b/lib/views/pages/user/land_page.dart index d4a56737..1e90af98 100644 --- a/lib/views/pages/user/land_page.dart +++ b/lib/views/pages/user/land_page.dart @@ -23,7 +23,7 @@ import 'package:test_sa/views/app_style/colors.dart'; import 'package:test_sa/views/app_style/sizing.dart'; import 'package:test_sa/views/pages/device_transfer/request_device_transfer.dart'; import 'package:test_sa/views/pages/device_transfer/track_device_transfer.dart'; -import 'package:test_sa/views/pages/sub_workorder/sub_workorder_page.dart'; +import 'package:test_sa/views/pages/sub_workorder/search_sub_workorder_page.dart'; import 'package:test_sa/views/pages/user/gas_refill/request_gas_refill.dart'; import 'package:test_sa/views/pages/user/gas_refill/track_gas_refill.dart'; import 'package:test_sa/views/pages/user/requests/create_request.dart'; @@ -217,7 +217,7 @@ class _LandPageState extends State { text: "Search Work Order", svgPath: "assets/images/sub_workorder_icon.svg", onPressed: () { - Navigator.of(context).pushNamed(SubWorkOrderPage.id); + Navigator.of(context).pushNamed(SearchSubWorkOrderPage.id); }, ), ], From e2a21040871f9d874213b3a4b8df3a7e832b7624 Mon Sep 17 00:00:00 2001 From: zaid_daoud Date: Mon, 19 Jun 2023 09:52:12 +0300 Subject: [PATCH 2/3] Preparing the functionality [Still doesn't work] --- .../api/service_requests_provider.dart | 6 +-- .../create_sub_workorder_page.dart | 46 +++++++++++++++++-- .../spare_parts_details_bottom_sheet.dart | 33 ++++++++++++- .../work_order_details_bottom_sheet.dart | 35 +++++++++++++- 4 files changed, 111 insertions(+), 9 deletions(-) diff --git a/lib/controllers/providers/api/service_requests_provider.dart b/lib/controllers/providers/api/service_requests_provider.dart index 3334332b..755ffff0 100644 --- a/lib/controllers/providers/api/service_requests_provider.dart +++ b/lib/controllers/providers/api/service_requests_provider.dart @@ -445,10 +445,10 @@ class ServiceRequestsProvider extends ChangeNotifier { } Future updateServiceReport({ - @required String host, - @required User user, @required ServiceReport report, - @required ServiceRequest request, + String host, + User user, + ServiceRequest request, }) async { Response response; //Map body = report.toMap(request); diff --git a/lib/views/pages/sub_workorder/create_sub_workorder_page.dart b/lib/views/pages/sub_workorder/create_sub_workorder_page.dart index a0a8889f..203852b9 100644 --- a/lib/views/pages/sub_workorder/create_sub_workorder_page.dart +++ b/lib/views/pages/sub_workorder/create_sub_workorder_page.dart @@ -1,17 +1,27 @@ import 'package:flutter/material.dart'; +import 'package:fluttertoast/fluttertoast.dart'; +import 'package:provider/provider.dart'; +import 'package:test_sa/controllers/providers/api/service_requests_provider.dart'; import 'package:test_sa/views/app_style/colors.dart'; import 'package:test_sa/views/pages/sub_workorder/spare_parts_details_bottom_sheet.dart'; import 'package:test_sa/views/pages/sub_workorder/work_order_details_bottom_sheet.dart'; +import '../../../controllers/api_routes/http_status_manger.dart'; import '../../../controllers/localization/localization.dart'; import '../../../models/subtitle.dart'; import '../../widgets/buttons/app_back_button.dart'; import '../../widgets/buttons/app_button.dart'; -class CreateSubWorkOrderPage extends StatelessWidget { +class CreateSubWorkOrderPage extends StatefulWidget { static const id = "/CreateSubWorkOrder"; const CreateSubWorkOrderPage({Key key}) : super(key: key); + @override + State createState() => _CreateSubWorkOrderPageState(); +} + +class _CreateSubWorkOrderPageState extends State { + final GlobalKey _formKey = GlobalKey(); @override Widget build(BuildContext context) { final Subtitle subtitle = AppLocalization.of(context).subtitle; @@ -111,8 +121,38 @@ class CreateSubWorkOrderPage extends StatelessWidget { floatingActionButton: Padding( padding: const EdgeInsets.all(16.0), child: AButton( - text: subtitle.update, - onPressed: () {}, + text: subtitle.create, + onPressed: () async { + // validate = true; + // if (!_formKey.currentState.validate()) { + // setState(() {}); + // return; + // } + // if (!_serviceReport.validate()) return; + _formKey.currentState.save(); + + // _isLoading = true; + setState(() {}); + + int status = await Provider.of(context).createServiceReport( + // user: _userProvider.user, + // host: _settingProvider.host, + // report: _serviceReport, + // request: widget.request, + ); + // _isLoading = false; + setState(() {}); + if (status >= 200 && status < 300) { + Fluttertoast.showToast(msg: subtitle.requestCompleteSuccessfully); + Navigator.of(context).pop(); + Navigator.of(context).pop(); + } else { + String errorMessage = HttpStatusManger.getStatusMessage(status: status, subtitle: subtitle); + ScaffoldMessenger.of(context).showSnackBar(SnackBar( + content: Text(errorMessage), + )); + } + }, ), ), ); diff --git a/lib/views/pages/sub_workorder/spare_parts_details_bottom_sheet.dart b/lib/views/pages/sub_workorder/spare_parts_details_bottom_sheet.dart index 0af019bf..a1a7887a 100644 --- a/lib/views/pages/sub_workorder/spare_parts_details_bottom_sheet.dart +++ b/lib/views/pages/sub_workorder/spare_parts_details_bottom_sheet.dart @@ -1,7 +1,12 @@ import 'package:flutter/material.dart'; +import 'package:fluttertoast/fluttertoast.dart'; +import 'package:provider/provider.dart'; import 'package:test_sa/views/app_style/colors.dart'; +import '../../../controllers/api_routes/http_status_manger.dart'; import '../../../controllers/localization/localization.dart'; +import '../../../controllers/providers/api/service_requests_provider.dart'; +import '../../../models/service_report.dart'; import '../../../models/subtitle.dart'; import '../../widgets/app_text_form_field.dart'; import '../../widgets/buttons/app_button.dart'; @@ -118,7 +123,33 @@ class _SparePartsBottomSheetState extends State { ), AButton( text: subtitle.update, - onPressed: () {}, + onPressed: () async { + // _validate = true; + if (!_formKey.currentState.validate()) { + setState(() {}); + return; + } + // if (!_serviceReport.validate()) { + // setState(() {}); + // return; + // } + _formKey.currentState.save(); + + // _isLoading = true; + setState(() {}); + + int status = await Provider.of(context).updateServiceReport(report: ServiceReport()); + // _isLoading = false; + setState(() {}); + if (status >= 200 && status < 300) { + Fluttertoast.showToast(msg: subtitle.requestCompleteSuccessfully); + Navigator.of(context).pop(); + // Navigator.of(context).pop(); + } else { + String errorMessage = HttpStatusManger.getStatusMessage(status: status, subtitle: subtitle); + ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text(errorMessage))); + } + }, ), ], ), diff --git a/lib/views/pages/sub_workorder/work_order_details_bottom_sheet.dart b/lib/views/pages/sub_workorder/work_order_details_bottom_sheet.dart index 718f4348..1efa95ba 100644 --- a/lib/views/pages/sub_workorder/work_order_details_bottom_sheet.dart +++ b/lib/views/pages/sub_workorder/work_order_details_bottom_sheet.dart @@ -1,11 +1,16 @@ import 'package:flutter/material.dart'; +import 'package:fluttertoast/fluttertoast.dart'; +import 'package:provider/provider.dart'; +import 'package:test_sa/controllers/providers/api/service_requests_provider.dart'; import 'package:test_sa/models/subtitle.dart'; import 'package:test_sa/views/widgets/app_text_form_field.dart'; import 'package:test_sa/views/widgets/buttons/app_button.dart'; import 'package:test_sa/views/widgets/status/report/service_report_maintenance_situation.dart'; import 'package:test_sa/views/widgets/status/report/service_report_repair_location.dart'; +import '../../../controllers/api_routes/http_status_manger.dart'; import '../../../controllers/localization/localization.dart'; +import '../../../models/service_report.dart'; import '../../app_style/sizing.dart'; import '../../widgets/date_and_time/time_picker.dart'; import '../../widgets/status/report/service_report_all_users.dart'; @@ -117,7 +122,7 @@ class _WorkOrderDetailsBottomSheetState extends State Validator.isNumeric(value) ? null : _subtitle.requiredWord, textInputType: TextInputType.number, onSaved: (value) { @@ -169,7 +174,33 @@ class _WorkOrderDetailsBottomSheetState extends State(context).updateServiceReport(report: ServiceReport()); + // _isLoading = false; + setState(() {}); + if (status >= 200 && status < 300) { + Fluttertoast.showToast(msg: subtitle.requestCompleteSuccessfully); + Navigator.of(context).pop(); + // Navigator.of(context).pop(); + } else { + String errorMessage = HttpStatusManger.getStatusMessage(status: status, subtitle: subtitle); + ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text(errorMessage))); + } + }, ), ], ), From 4fac73cd67e26a2015239e29497d77631ca65c2f Mon Sep 17 00:00:00 2001 From: zaid_daoud Date: Mon, 19 Jun 2023 10:49:52 +0300 Subject: [PATCH 3/3] Preparing the functionality [Still doesn't work] --- .../service_request/search_work_order.dart | 8 ++ .../create_sub_workorder_page.dart | 8 +- .../search_sub_workorder_page.dart | 16 +++- .../spare_parts_details_bottom_sheet.dart | 88 +++++++++++-------- .../work_order_details_bottom_sheet.dart | 86 ++++++++++++------ 5 files changed, 133 insertions(+), 73 deletions(-) diff --git a/lib/models/service_request/search_work_order.dart b/lib/models/service_request/search_work_order.dart index 713e9125..0fc6907b 100644 --- a/lib/models/service_request/search_work_order.dart +++ b/lib/models/service_request/search_work_order.dart @@ -10,6 +10,8 @@ class SearchWorkOrders { String assetType; AssignedEmployee assignedEmployee; String visitDate; + String startDate; + String endDate; List assistantEmployees; String supplier; String vendorTicketNumber; @@ -44,6 +46,8 @@ class SearchWorkOrders { this.assetType, this.assignedEmployee, this.visitDate, + this.startDate, + this.endDate, this.assistantEmployees, this.supplier, this.vendorTicketNumber, @@ -79,6 +83,8 @@ class SearchWorkOrders { assetType = json['assetType']; assignedEmployee = json['assignedEmployee'] != null ? new AssignedEmployee.fromJson(json['assignedEmployee']) : AssignedEmployee(); visitDate = json['visitDate']; + startDate = json['startDate']; + endDate = json['endDate']; if (json['assistantEmployees'] != null) { assistantEmployees = json['assistantEmployees']; } @@ -127,6 +133,8 @@ class SearchWorkOrders { data['assignedEmployee'] = this.assignedEmployee.toJson(); } data['visitDate'] = this.visitDate; + data['startDate'] = this.startDate; + data['endDate'] = this.endDate; if (this.assistantEmployees != null) { data['assistantEmployees'] = this.assistantEmployees.map((v) => v.toJson()).toList(); } diff --git a/lib/views/pages/sub_workorder/create_sub_workorder_page.dart b/lib/views/pages/sub_workorder/create_sub_workorder_page.dart index 203852b9..1619e536 100644 --- a/lib/views/pages/sub_workorder/create_sub_workorder_page.dart +++ b/lib/views/pages/sub_workorder/create_sub_workorder_page.dart @@ -2,6 +2,7 @@ import 'package:flutter/material.dart'; import 'package:fluttertoast/fluttertoast.dart'; import 'package:provider/provider.dart'; import 'package:test_sa/controllers/providers/api/service_requests_provider.dart'; +import 'package:test_sa/models/service_request/search_work_order.dart'; import 'package:test_sa/views/app_style/colors.dart'; import 'package:test_sa/views/pages/sub_workorder/spare_parts_details_bottom_sheet.dart'; import 'package:test_sa/views/pages/sub_workorder/work_order_details_bottom_sheet.dart'; @@ -14,7 +15,8 @@ import '../../widgets/buttons/app_button.dart'; class CreateSubWorkOrderPage extends StatefulWidget { static const id = "/CreateSubWorkOrder"; - const CreateSubWorkOrderPage({Key key}) : super(key: key); + final SearchWorkOrders workOrder; + const CreateSubWorkOrderPage({this.workOrder, Key key}) : super(key: key); @override State createState() => _CreateSubWorkOrderPageState(); @@ -66,7 +68,7 @@ class _CreateSubWorkOrderPageState extends State { useSafeArea: true, isScrollControlled: true, backgroundColor: Colors.transparent, - builder: (context) => const WorkOrderDetailsBottomSheet(), + builder: (context) => WorkOrderDetailsBottomSheet(workOrder: widget.workOrder), ); }, child: Card( @@ -92,7 +94,7 @@ class _CreateSubWorkOrderPageState extends State { useSafeArea: true, isScrollControlled: true, backgroundColor: Colors.transparent, - builder: (context) => const SparePartsBottomSheet(), + builder: (context) => SparePartsBottomSheet(workOrder: widget.workOrder), ); }, child: Card( diff --git a/lib/views/pages/sub_workorder/search_sub_workorder_page.dart b/lib/views/pages/sub_workorder/search_sub_workorder_page.dart index e7747ace..6e9ae74a 100644 --- a/lib/views/pages/sub_workorder/search_sub_workorder_page.dart +++ b/lib/views/pages/sub_workorder/search_sub_workorder_page.dart @@ -5,6 +5,7 @@ import 'package:test_sa/models/engineer.dart'; import 'package:test_sa/models/lookup.dart'; import 'package:test_sa/models/service_request/search_work_order.dart'; import 'package:test_sa/models/subtitle.dart'; +import 'package:test_sa/views/pages/sub_workorder/create_sub_workorder_page.dart'; import 'package:test_sa/views/widgets/app_text_form_field.dart'; import 'package:test_sa/views/widgets/date_and_time/date_picker.dart'; @@ -14,7 +15,6 @@ import '../../../controllers/providers/api/service_requests_provider.dart'; import '../../app_style/colors.dart'; import '../../widgets/buttons/app_back_button.dart'; import '../../widgets/buttons/app_button.dart'; -import '../../widgets/loaders/app_loading.dart'; import '../../widgets/status/report/service_report_all_users.dart'; import '../../widgets/status/report/service_report_maintenance_situation.dart'; import '../../widgets/status/report/service_report_visit_date_operator.dart'; @@ -160,7 +160,7 @@ class _SearchSubWorkOrderPageState extends State { ), floatingActionButtonLocation: FloatingActionButtonLocation.centerFloat, floatingActionButton: _isLoading - ? const ALoading() + ? const CircularProgressIndicator() : Padding( padding: const EdgeInsets.symmetric(horizontal: 16), child: AButton( @@ -188,8 +188,16 @@ class _SearchSubWorkOrderPageState extends State { body: ListView.builder( itemCount: woList.length, shrinkWrap: true, - itemBuilder: (context, index) => Text( - woList[index].id?.toString(), + itemBuilder: (context, index) => InkWell( + onTap: () { + Navigator.push( + context, + MaterialPageRoute(builder: (context) => CreateSubWorkOrderPage(workOrder: woList[index])), + ); + }, + child: Text( + woList[index].id?.toString(), + ), ), ), ), diff --git a/lib/views/pages/sub_workorder/spare_parts_details_bottom_sheet.dart b/lib/views/pages/sub_workorder/spare_parts_details_bottom_sheet.dart index a1a7887a..048a6158 100644 --- a/lib/views/pages/sub_workorder/spare_parts_details_bottom_sheet.dart +++ b/lib/views/pages/sub_workorder/spare_parts_details_bottom_sheet.dart @@ -1,6 +1,7 @@ import 'package:flutter/material.dart'; import 'package:fluttertoast/fluttertoast.dart'; import 'package:provider/provider.dart'; +import 'package:test_sa/models/service_request/search_work_order.dart'; import 'package:test_sa/views/app_style/colors.dart'; import '../../../controllers/api_routes/http_status_manger.dart'; @@ -13,7 +14,8 @@ import '../../widgets/buttons/app_button.dart'; import '../../widgets/titles/app_sub_title.dart'; class SparePartsBottomSheet extends StatefulWidget { - const SparePartsBottomSheet({Key key}) : super(key: key); + final SearchWorkOrders workOrder; + const SparePartsBottomSheet({this.workOrder, Key key}) : super(key: key); @override State createState() => _SparePartsBottomSheetState(); @@ -21,6 +23,14 @@ class SparePartsBottomSheet extends StatefulWidget { class _SparePartsBottomSheetState extends State { final GlobalKey _formKey = GlobalKey(); + SearchWorkOrders _workOrder; + bool _isLoading = false; + @override + void initState() { + super.initState(); + _workOrder = widget.workOrder; + } + @override Widget build(BuildContext context) { final size = MediaQuery.of(context).size; @@ -53,42 +63,46 @@ class _SparePartsBottomSheetState extends State { crossAxisAlignment: CrossAxisAlignment.start, children: [ const SizedBox(height: 8), - ListView.builder( - itemCount: 1, - shrinkWrap: true, - physics: const NeverScrollableScrollPhysics(), - itemBuilder: (context, index) => Column( - children: [ - const ATextFormField(labelText: "Part No."), - const SizedBox(height: 8), - const ATextFormField( - labelText: "Description", - hintText: "Add Some Text", - textInputType: TextInputType.multiline, - ), - const SizedBox(height: 8), - const ATextFormField( - labelText: "Quantity", - textInputType: TextInputType.number, - ), - const SizedBox(height: 8), - InkWell( - onTap: () {}, - child: Row( - mainAxisAlignment: MainAxisAlignment.end, - children: [ - const Icon(Icons.delete, color: Colors.red), - Text( - "Remove this part", - style: Theme.of(context).textTheme.bodySmall, + if (_workOrder.sparePartsWorkOrders?.length != null) + ListView.builder( + itemCount: _workOrder.sparePartsWorkOrders?.length, + shrinkWrap: true, + physics: const NeverScrollableScrollPhysics(), + itemBuilder: (context, index) { + final wo = _workOrder.sparePartsWorkOrders[index]; + return Column( + children: [ + const ATextFormField(labelText: "Part No."), + const SizedBox(height: 8), + const ATextFormField( + labelText: "Description", + hintText: "Add Some Text", + textInputType: TextInputType.multiline, + ), + const SizedBox(height: 8), + const ATextFormField( + labelText: "Quantity", + textInputType: TextInputType.number, + ), + const SizedBox(height: 8), + InkWell( + onTap: () {}, + child: Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + const Icon(Icons.delete, color: Colors.red), + Text( + "Remove this part", + style: Theme.of(context).textTheme.bodySmall, + ), + ], ), - ], - ), - ), - const SizedBox(height: 8), - ], + ), + const SizedBox(height: 8), + ], + ); + }, ), - ), const Divider(), const SizedBox(height: 8), InkWell( @@ -135,11 +149,11 @@ class _SparePartsBottomSheetState extends State { // } _formKey.currentState.save(); - // _isLoading = true; + _isLoading = true; setState(() {}); int status = await Provider.of(context).updateServiceReport(report: ServiceReport()); - // _isLoading = false; + _isLoading = false; setState(() {}); if (status >= 200 && status < 300) { Fluttertoast.showToast(msg: subtitle.requestCompleteSuccessfully); diff --git a/lib/views/pages/sub_workorder/work_order_details_bottom_sheet.dart b/lib/views/pages/sub_workorder/work_order_details_bottom_sheet.dart index 1efa95ba..12df4c57 100644 --- a/lib/views/pages/sub_workorder/work_order_details_bottom_sheet.dart +++ b/lib/views/pages/sub_workorder/work_order_details_bottom_sheet.dart @@ -2,6 +2,8 @@ import 'package:flutter/material.dart'; import 'package:fluttertoast/fluttertoast.dart'; import 'package:provider/provider.dart'; import 'package:test_sa/controllers/providers/api/service_requests_provider.dart'; +import 'package:test_sa/models/lookup.dart'; +import 'package:test_sa/models/service_request/search_work_order.dart'; import 'package:test_sa/models/subtitle.dart'; import 'package:test_sa/views/widgets/app_text_form_field.dart'; import 'package:test_sa/views/widgets/buttons/app_button.dart'; @@ -10,6 +12,7 @@ import 'package:test_sa/views/widgets/status/report/service_report_repair_locati import '../../../controllers/api_routes/http_status_manger.dart'; import '../../../controllers/localization/localization.dart'; +import '../../../models/engineer.dart'; import '../../../models/service_report.dart'; import '../../app_style/sizing.dart'; import '../../widgets/date_and_time/time_picker.dart'; @@ -17,7 +20,8 @@ import '../../widgets/status/report/service_report_all_users.dart'; import '../../widgets/titles/app_sub_title.dart'; class WorkOrderDetailsBottomSheet extends StatefulWidget { - const WorkOrderDetailsBottomSheet({Key key}) : super(key: key); + final SearchWorkOrders workOrder; + const WorkOrderDetailsBottomSheet({this.workOrder, Key key}) : super(key: key); @override State createState() => _WorkOrderDetailsBottomSheetState(); @@ -25,6 +29,15 @@ class WorkOrderDetailsBottomSheet extends StatefulWidget { class _WorkOrderDetailsBottomSheetState extends State { final GlobalKey _formKey = GlobalKey(); + SearchWorkOrders _workOrder; + bool _isLoading = false; + + @override + void initState() { + super.initState(); + _workOrder = widget.workOrder; + } + @override Widget build(BuildContext context) { final size = MediaQuery.of(context).size; @@ -56,14 +69,16 @@ class _WorkOrderDetailsBottomSheetState extends State Validator.isNumeric(value) ? null : _subtitle.requiredWord, textInputType: TextInputType.number, onSaved: (value) { - // _serviceReport.workHours = value; + _workOrder.workingHours = double.tryParse(value); }, ), const SizedBox(height: 8), - const ATextFormField( + ATextFormField( labelText: "Travel Hours", + initialValue: _workOrder.travelingHours?.toString(), + textInputType: TextInputType.number, + onSaved: (value) { + _workOrder.travelingHours = num.tryParse(value); + }, ), const SizedBox(height: 8), - const ATextFormField( + ATextFormField( labelText: "Travel Expense", + initialValue: _workOrder.travelingExpenses?.toString(), + textInputType: TextInputType.number, + onSaved: (value) { + _workOrder.travelingExpenses = num.tryParse(value); + }, ), const SizedBox(height: 8), ASubTitle(subtitle.callLastSituation), const SizedBox(height: 4), ServiceReportMaintenanceSituation( - initialValue: null /*_searchWorkOrders.calllastSituation*/, + initialValue: _workOrder.calllastSituation, onSelect: (status) { - // if (status?.value == 12 || _searchWorkOrders.calllastSituation?.value == 12) { - // _searchWorkOrders.calllastSituation = status; - // setState(() {}); - // } else { - // _searchWorkOrders.calllastSituation = status; - // } + if (status?.value == 12 || _workOrder.calllastSituation?.value == 12) { + _workOrder.calllastSituation = status; + setState(() {}); + } else { + _workOrder.calllastSituation = status; + } }, ), const SizedBox(height: 8), const ASubTitle("Repair Location"), const SizedBox(height: 4), ServiceReportRepairLocation( - // initialValue: _serviceReport.repairLocation, + initialValue: _workOrder.repairLocation != null ? Lookup(name: _workOrder.repairLocation) : null, onSelect: (status) { - // _serviceReport.repairLocation = status; + _workOrder.repairLocation = status.name; }, ), const SizedBox(height: 8), - const ATextFormField( + ATextFormField( labelText: "Technical Comments", - hintText: "Add Some Text", + initialValue: _workOrder.reviewComment, textInputType: TextInputType.multiline, + onSaved: (value) { + _workOrder.reviewComment = value; + }, ), const SizedBox(height: 24), ], @@ -186,11 +214,11 @@ class _WorkOrderDetailsBottomSheetState extends State(context).updateServiceReport(report: ServiceReport()); - // _isLoading = false; + _isLoading = false; setState(() {}); if (status >= 200 && status < 300) { Fluttertoast.showToast(msg: subtitle.requestCompleteSuccessfully);