diff --git a/lib/controllers/api_routes/urls.dart b/lib/controllers/api_routes/urls.dart index a587fb7..33eef04 100644 --- a/lib/controllers/api_routes/urls.dart +++ b/lib/controllers/api_routes/urls.dart @@ -51,6 +51,7 @@ class URLs { static get updateRegularVisits => "$_baseUrl/Visit/UpdateVisits"; // get static get getSingleServiceRequest => "$_baseUrl/return/call/information"; // get + static get getSuppliersAutoComplete => "$_baseUrl/Supplier/GetSuppliersAutoComplete"; static get getNotifications => "$_baseUrl/return/user/notification"; // get static get getRecentNotifications => "$_baseUrl/return/user/recent/notification"; // get static get createRequest => "$_baseUrl/CallRequest/AddCallRequest"; // get diff --git a/lib/controllers/providers/api/status_drop_down/report/vendor_provider.dart b/lib/controllers/providers/api/status_drop_down/report/vendor_provider.dart new file mode 100644 index 0000000..4271e00 --- /dev/null +++ b/lib/controllers/providers/api/status_drop_down/report/vendor_provider.dart @@ -0,0 +1,53 @@ +import 'dart:convert'; + +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:http/http.dart'; +import 'package:test_sa/controllers/api_routes/api_manager.dart'; +import 'package:test_sa/controllers/api_routes/urls.dart'; +import 'package:test_sa/models/service_request/search_work_order.dart'; + +class VendorProvider extends ChangeNotifier { + void reset() { + _vendors = null; + _loading = null; + _stateCode = null; + } + + int _stateCode; + int get stateCode => _stateCode; + + List _vendors; + List get vendors => _vendors; + + bool _loading; + bool get isLoading => _loading; + set isLoading(bool isLoading) { + _loading = isLoading; + notifyListeners(); + } + + Future getVendors(String text) async { + if (_loading == true) return -2; + _loading = true; + notifyListeners(); + Response response; + try { + response = await ApiManager.instance.get("${URLs.getSuppliersAutoComplete}?searchText=$text"); + _stateCode = response.statusCode; + if (response.statusCode >= 200 && response.statusCode < 300) { + // client's request was successfully received + List suppliersJson = json.decode(response.body)["data"]; + _vendors = suppliersJson.map((type) => Supplier.fromJson(type)).toList(); + } + _loading = false; + notifyListeners(); + return response.statusCode; + } catch (error) { + _loading = false; + _stateCode = -1; + notifyListeners(); + return -1; + } + } +} diff --git a/lib/main.dart b/lib/main.dart index 466e052..03427e4 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -63,6 +63,7 @@ import 'controllers/providers/api/status_drop_down/report/service_report_repair_ import 'controllers/providers/api/status_drop_down/report/service_report_status_provider.dart'; import 'controllers/providers/api/status_drop_down/report/service_report_types_provider.dart'; import 'controllers/providers/api/status_drop_down/report/service_types_provider.dart'; +import 'controllers/providers/api/status_drop_down/report/vendor_provider.dart'; import 'controllers/providers/api/user_provider.dart'; import 'controllers/providers/settings/setting_provider.dart'; import 'views/pages/device_transfer/request_device_transfer.dart'; @@ -81,15 +82,17 @@ void main() async { } runApp(ChangeNotifierProvider( create: (_) => SettingProvider(), - child: MyApp(), + child: const MyApp(), )); } class MyApp extends StatelessWidget { + const MyApp({Key key}) : super(key: key); + // This widget is the root of your application. @override Widget build(BuildContext context) { - final _settingProvider = Provider.of(context); + final settingProvider = Provider.of(context); return MultiProvider( providers: [ ChangeNotifierProvider(create: (_) => UserProvider()), @@ -131,6 +134,7 @@ class MyApp extends StatelessWidget { ChangeNotifierProvider(create: (_) => ServiceReportMaintenanceSituationProvider()), ChangeNotifierProvider(create: (_) => ServiceReportUsersProvider()), ChangeNotifierProvider(create: (_) => ServiceReportAssistantsEmployeeProvider()), + ChangeNotifierProvider(create: (_) => VendorProvider()), ], child: GestureDetector( onTap: () { @@ -160,7 +164,7 @@ class MyApp extends StatelessWidget { Locale('en'), Locale('ar'), ], - locale: Locale(_settingProvider.language ?? 'en'), + locale: Locale(settingProvider.language ?? 'en'), initialRoute: SplashScreen.id, routes: { SplashScreen.id: (_) => const SplashScreen(), diff --git a/lib/models/service_request/search_work_order.dart b/lib/models/service_request/search_work_order.dart index 7f4efa5..564b7dd 100644 --- a/lib/models/service_request/search_work_order.dart +++ b/lib/models/service_request/search_work_order.dart @@ -286,7 +286,7 @@ class SearchWorkOrder { if (repairLocation?.id != null) { map['repairLocation'] = repairLocation.toMap(); } - if (reason != null) { + if (reason != null && reason.id != null) { map['reason'] = reason.toMap(); } // map['startofWorkTime'] = startofWorkTime; @@ -308,7 +308,7 @@ class SearchWorkOrder { if (attachmentsWorkOrder != null) { map['attachmentsWorkOrder'] = attachmentsWorkOrder.map((v) => v.toJson()).toList(); } - if (equipmentStatus != null) { + if (equipmentStatus != null && equipmentStatus.id != null) { map['equipmentStatus'] = equipmentStatus.toMap(); } if (suppEngineerWorkOrders != null) { @@ -2719,29 +2719,42 @@ class Supplier { Supplier({ this.id, this.suppliername, + this.suppPersons, }); Supplier.fromJson(dynamic json) { id = json['id']; suppliername = json['suppliername']; + if (json['suppPersons'] != null) { + suppPersons = []; + json['suppPersons'].forEach((v) { + suppPersons.add(SuppPersons.fromJson(v)); + }); + } } num id; String suppliername; + List suppPersons; SupplierModel copyWith({ num id, String suppliername, + List suppPersons, }) => SupplierModel( id: id ?? this.id, suppliername: suppliername ?? this.suppliername, + suppPersons: suppPersons ?? this.suppPersons, ); Map toJson() { final map = {}; map['id'] = id ?? 0; map['suppliername'] = suppliername; + if (suppPersons != null) { + map['suppPersons'] = suppPersons.map((v) => v.toJson()).toList(); + } return map; } } diff --git a/lib/views/pages/sub_workorder/auto_generated_vendor_name.dart b/lib/views/pages/sub_workorder/auto_generated_vendor_name.dart new file mode 100644 index 0000000..41244de --- /dev/null +++ b/lib/views/pages/sub_workorder/auto_generated_vendor_name.dart @@ -0,0 +1,85 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_typeahead/flutter_typeahead.dart'; +import 'package:provider/provider.dart'; +import 'package:test_sa/models/service_request/search_work_order.dart'; + +import '../../../controllers/providers/api/status_drop_down/report/vendor_provider.dart'; +import '../../app_style/colors.dart'; +import '../../app_style/sizing.dart'; + +class AutoGeneratedVendorName extends StatefulWidget { + final String initialValue; + final Function(Supplier) onSearch; + const AutoGeneratedVendorName({Key key, this.initialValue, this.onSearch}) : super(key: key); + + @override + State createState() => _AutoGeneratedVendorNameState(); +} + +class _AutoGeneratedVendorNameState extends State { + TextEditingController _controller; + + @override + void initState() { + super.initState(); + _controller = TextEditingController(text: widget.initialValue ?? ""); + } + + @override + void didUpdateWidget(covariant AutoGeneratedVendorName oldWidget) { + super.didUpdateWidget(oldWidget); + + if (oldWidget.initialValue != widget.initialValue) { + _controller = TextEditingController(text: widget.initialValue ?? ""); + } + } + + @override + void dispose() { + _controller.dispose(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + final vendorProvider = Provider.of(context, listen: false); + return Container( + padding: const EdgeInsets.symmetric(horizontal: 16), + decoration: BoxDecoration( + color: AColors.inputFieldBackgroundColor, + border: Border.all( + color: const Color(0xffefefef), + ), + borderRadius: BorderRadius.circular(AppStyle.borderRadius * AppStyle.getScaleFactor(context)), + // boxShadow: [ + // AppStyle.boxShadow + // ] + ), + child: TypeAheadField( + textFieldConfiguration: TextFieldConfiguration( + style: Theme.of(context).textTheme.titleLarge, + controller: _controller, + textAlign: TextAlign.center, + decoration: const InputDecoration( + hintText: "Vendor Name", + border: InputBorder.none, + disabledBorder: InputBorder.none, + focusedBorder: InputBorder.none, + enabledBorder: InputBorder.none, + ), + textInputAction: TextInputAction.search, + ), + suggestionsCallback: (vale) async { + await vendorProvider.getVendors(_controller.text.trim()); + return vendorProvider.vendors; + }, + itemBuilder: (context, vendor) { + return ListTile(title: Text(vendor.suppliername)); + }, + onSuggestionSelected: (hospital) { + widget.onSearch(hospital); + }, + ), + ); + } +} 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 fdfd67e..f022539 100644 --- a/lib/views/pages/sub_workorder/create_sub_workorder_page.dart +++ b/lib/views/pages/sub_workorder/create_sub_workorder_page.dart @@ -58,6 +58,7 @@ class _CreateSubWorkOrderPageState extends State { callRequest: CallRequest(id: widget?.workOrder?.callRequest?.id), currentSituation: null, supplier: null, + parentWOId: widget.workOrder.id, ); _serviceReport = ServiceReport(id: widget.workOrder.id, type: widget.workOrder.assetType, equipmentStatus: widget.workOrder.equipmentStatus); _isLoading = true; @@ -313,7 +314,6 @@ class _CreateSubWorkOrderPageState extends State { child: AButton( text: subtitle.create, onPressed: () async { - _subWorkOrders.parentWOId = widget.workOrder.id; _validate = true; setState(() {}); if (validate()) { 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 e91de02..ab6ff1b 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 @@ -8,11 +8,13 @@ import 'package:test_sa/views/widgets/buttons/app_button.dart'; import 'package:test_sa/views/widgets/status/report/service_report_assistant_employee_menu.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 'package:test_sa/views/widgets/status/service_request/supplier_engineers_menu.dart'; import '../../../controllers/localization/localization.dart'; import '../../../controllers/providers/api/status_drop_down/report/service_report_maintenance_situation_provider.dart'; import '../../widgets/timer/app_timer.dart'; import '../../widgets/titles/app_sub_title.dart'; +import 'auto_generated_vendor_name.dart'; class WorkOrderDetailsBottomSheet extends StatefulWidget { final SearchWorkOrder subWorkOrder; @@ -25,12 +27,18 @@ class WorkOrderDetailsBottomSheet extends StatefulWidget { class _WorkOrderDetailsBottomSheetState extends State { final GlobalKey _formKey = GlobalKey(); final SearchWorkOrder _workOrder = SearchWorkOrder(); + bool _showVendorFields = false; + SuppEngineerWorkOrders engineer; @override void initState() { super.initState(); _workOrder.copyFrom(widget.subWorkOrder); + if (_workOrder.calllastSituation?.name?.toLowerCase()?.contains("under repair-vendor") ?? false) { + _showVendorFields = true; + _workOrder.supplier ??= SupplierModel(id: _workOrder?.supplier?.id); + } if (context.mounted) { Provider.of(context, listen: false).reset(); } @@ -118,6 +126,14 @@ class _WorkOrderDetailsBottomSheetState extends State engineers; + final SuppEngineerWorkOrders initialValue; + final Function(SuppEngineerWorkOrders) onSelect; + + const SupplierEngineersMenu({Key key, this.engineers, this.onSelect, this.initialValue}) : super(key: key); + + @override + SingleAssistantEmployeeMenuState createState() => SingleAssistantEmployeeMenuState(); +} + +class SingleAssistantEmployeeMenuState extends State { + SuppPersons _selectedEngineer; + + @override + void setState(VoidCallback fn) { + if (mounted) super.setState(fn); + } + + @override + void didUpdateWidget(covariant SupplierEngineersMenu oldWidget) { + if (widget.initialValue != null) { + final result = widget.engineers?.where((element) { + return element?.id == widget.initialValue?.supplierContactId; + }); + if (result.isNotEmpty) { + _selectedEngineer = result.first; + } else { + _selectedEngineer = null; + } + if ((widget.initialValue?.supplierContactId ?? "") != (_selectedEngineer?.id ?? "")) { + onSelect(_selectedEngineer); + } + } else { + _selectedEngineer = null; + } + super.didUpdateWidget(oldWidget); + } + + @override + void initState() { + if (widget.initialValue != null) { + final result = widget.engineers?.where((element) { + return element?.id == widget.initialValue?.supplierContactId; + }); + if (result.isNotEmpty) _selectedEngineer = result.first; + if (widget.initialValue?.supplierContactId != _selectedEngineer?.id) { + onSelect(_selectedEngineer); + } + } + + super.initState(); + } + + @override + Widget build(BuildContext context) { + return Container( + padding: const EdgeInsets.symmetric(horizontal: 16), + decoration: BoxDecoration( + color: AColors.inputFieldBackgroundColor, + border: Border.all( + color: const Color(0xffefefef), + ), + borderRadius: BorderRadius.circular(AppStyle.borderRadius * AppStyle.getScaleFactor(context)), + // boxShadow: const [ + // AppStyle.boxShadow + // ] + ), + child: DropdownButton( + value: _selectedEngineer, + iconSize: 24, + icon: const Icon(Icons.keyboard_arrow_down_rounded), + elevation: 0, + isExpanded: true, + hint: Text("Vendor Engineer", style: Theme.of(context).textTheme.titleMedium), + style: TextStyle(color: Theme.of(context).primaryColor), + underline: const SizedBox.shrink(), + onChanged: (SuppPersons newValue) { + setState(() { + _selectedEngineer = newValue; + }); + onSelect(newValue); + }, + items: widget.engineers?.map>((SuppPersons value) { + return DropdownMenuItem( + value: value, + child: Text( + value?.personName ?? "NULL", + style: Theme.of(context).textTheme.titleMedium.copyWith( + color: Theme.of(context).primaryColor, + fontSize: 11, + //fontWeight: FontWeight.bold + ), + ), + ); + })?.toList(), + ), + ); + } + + void onSelect(SuppPersons engineer) { + widget.onSelect( + SuppEngineerWorkOrders( + id: engineer?.supplierId, + supplierContactId: engineer?.id, + personName: engineer?.personName, + contact: engineer?.contact, + externalEngCode: engineer?.externalEngCode, + email: engineer?.email, + ), + ); + } +}