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); }, ), ],