traf request creation completed.
							parent
							
								
									dd19507fa1
								
							
						
					
					
						commit
						144951caec
					
				| @ -0,0 +1,64 @@ | ||||
| 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/new_models/asset_nd_auto_complete_by_dynamic_codes_model.dart'; | ||||
| import 'package:test_sa/models/new_models/users_based_on_search_model.dart'; | ||||
| import 'package:test_sa/models/service_request/spare_parts.dart'; | ||||
| 
 | ||||
| class UserSearchProvider extends ChangeNotifier { | ||||
|   // number of items call in each request | ||||
|   final pageItemNumber = 20; | ||||
| 
 | ||||
|   //reset provider data | ||||
|   void reset() { | ||||
|     _parts = null; | ||||
|     _stateCode = null; | ||||
|   } | ||||
| 
 | ||||
|   // state code of current request to defied error message | ||||
|   // like 400 customer request failed | ||||
|   // 500 service not available | ||||
|   int? _stateCode; | ||||
| 
 | ||||
|   int? get stateCode => _stateCode; | ||||
| 
 | ||||
|   // true if there is next pagein product list and false if not | ||||
|   bool _nextPage = true; | ||||
| 
 | ||||
|   bool get nextPage => _nextPage; | ||||
| 
 | ||||
|   // contain user data | ||||
|   // when user not login or register _user = null | ||||
|   List<SparePartsWorkOrders>? _parts; | ||||
| 
 | ||||
|   List<SparePartsWorkOrders>? get parts => _parts; | ||||
| 
 | ||||
|   bool _loading = false; | ||||
| 
 | ||||
|   bool get isLoading => _loading; | ||||
| 
 | ||||
|   set isLoading(bool isLoading) { | ||||
|     _loading = isLoading; | ||||
|     notifyListeners(); | ||||
|   } | ||||
| 
 | ||||
|   Future<List<UsersBasedOnSearchModel>> getUsersBasedOnSearch(String query) async { | ||||
|     late Response response; | ||||
|     try { | ||||
|       response = await ApiManager.instance.get(URLs.getUsersBasedOnSearch + "?searchText=$query"); | ||||
|       List<UsersBasedOnSearchModel> page = []; | ||||
|       if (response.statusCode >= 200 && response.statusCode < 300) { | ||||
|         // client's request was successfully received | ||||
|         List categoriesListJson = json.decode(response.body); | ||||
|         page = categoriesListJson.map((part) => UsersBasedOnSearchModel.fromJson(part)).toList(); | ||||
|       } | ||||
|       return page; | ||||
|     } catch (error) { | ||||
|       return []; | ||||
|     } | ||||
|   } | ||||
| } | ||||
| @ -0,0 +1,44 @@ | ||||
| class UsersBasedOnSearchModel { | ||||
|   String? userId; | ||||
|   String? userName; | ||||
|   String? email; | ||||
|   String? employeeId; | ||||
|   int? languageId; | ||||
|   String? extensionNo; | ||||
|   String? phoneNumber; | ||||
|   bool? isActive; | ||||
| 
 | ||||
|   UsersBasedOnSearchModel( | ||||
|       {this.userId, | ||||
|         this.userName, | ||||
|         this.email, | ||||
|         this.employeeId, | ||||
|         this.languageId, | ||||
|         this.extensionNo, | ||||
|         this.phoneNumber, | ||||
|         this.isActive}); | ||||
| 
 | ||||
|   UsersBasedOnSearchModel.fromJson(Map<String, dynamic> json) { | ||||
|     userId = json['userId']; | ||||
|     userName = json['userName']; | ||||
|     email = json['email']; | ||||
|     employeeId = json['employeeId']; | ||||
|     languageId = json['languageId']; | ||||
|     extensionNo = json['extensionNo']; | ||||
|     phoneNumber = json['phoneNumber']; | ||||
|     isActive = json['isActive']; | ||||
|   } | ||||
| 
 | ||||
|   Map<String, dynamic> toJson() { | ||||
|     final Map<String, dynamic> data = new Map<String, dynamic>(); | ||||
|     data['userId'] = this.userId; | ||||
|     data['userName'] = this.userName; | ||||
|     data['email'] = this.email; | ||||
|     data['employeeId'] = this.employeeId; | ||||
|     data['languageId'] = this.languageId; | ||||
|     data['extensionNo'] = this.extensionNo; | ||||
|     data['phoneNumber'] = this.phoneNumber; | ||||
|     data['isActive'] = this.isActive; | ||||
|     return data; | ||||
|   } | ||||
| } | ||||
| @ -0,0 +1,134 @@ | ||||
| import 'package:flutter/material.dart'; | ||||
| import 'package:provider/provider.dart'; | ||||
| import 'package:test_sa/controllers/providers/api/oracle_code_provider.dart'; | ||||
| import 'package:test_sa/controllers/providers/api/parts_provider.dart'; | ||||
| import 'package:test_sa/controllers/providers/api/search_user_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/new_models/asset_nd_auto_complete_by_dynamic_codes_model.dart'; | ||||
| import 'package:test_sa/models/new_models/users_based_on_search_model.dart'; | ||||
| import 'package:test_sa/new_views/app_style/app_color.dart'; | ||||
| import 'package:test_sa/views/app_style/sizing.dart'; | ||||
| 
 | ||||
| import '../../../extensions/text_extensions.dart'; | ||||
| import '../../../models/service_request/spare_parts.dart'; | ||||
| import '../../../new_views/app_style/app_text_style.dart'; | ||||
| 
 | ||||
| class SearchUserAutoCompleteField extends StatefulWidget { | ||||
|   final String initialValue; | ||||
|   final num? assetId; | ||||
|   final bool clearAfterPick, byName; | ||||
|   final Function(UsersBasedOnSearchModel) onPick; | ||||
| 
 | ||||
|   const SearchUserAutoCompleteField({Key? key, required this.byName, required this.initialValue, this.assetId, required this.onPick, this.clearAfterPick = true}) : super(key: key); | ||||
| 
 | ||||
|   @override | ||||
|   _UsersAutoCompleteFieldState createState() => _UsersAutoCompleteFieldState(); | ||||
| } | ||||
| 
 | ||||
| class _UsersAutoCompleteFieldState extends State<SearchUserAutoCompleteField> { | ||||
|   late UserSearchProvider _TechnologyUsersProvider; | ||||
| 
 | ||||
|   late TextEditingController _controller; | ||||
| 
 | ||||
|   bool loading = false; | ||||
| 
 | ||||
|   @override | ||||
|   void initState() { | ||||
|     _controller = TextEditingController(text: widget.initialValue); | ||||
|     super.initState(); | ||||
|     _TechnologyUsersProvider = Provider.of<UserSearchProvider>(context, listen: false); | ||||
|   } | ||||
| 
 | ||||
|   @override | ||||
|   void didUpdateWidget(covariant SearchUserAutoCompleteField oldWidget) { | ||||
|     if (widget.initialValue != oldWidget.initialValue) { | ||||
|       _controller = TextEditingController(text: widget.initialValue); | ||||
|     } | ||||
|     super.didUpdateWidget(oldWidget); | ||||
|   } | ||||
| 
 | ||||
|   @override | ||||
|   void dispose() { | ||||
|     _controller.dispose(); | ||||
|     super.dispose(); | ||||
|   } | ||||
| 
 | ||||
|   @override | ||||
|   Widget build(BuildContext context) { | ||||
|     final border = UnderlineInputBorder(borderSide: BorderSide.none, borderRadius: BorderRadius.circular(10)); | ||||
|     return Container( | ||||
|       decoration: BoxDecoration( | ||||
|         color: AppColor.background(context), | ||||
|         borderRadius: BorderRadius.circular(AppStyle.borderRadius * AppStyle.getScaleFactor(context)), | ||||
|         //  boxShadow: [BoxShadow(color: Colors.black.withOpacity(0.05), blurRadius: 10)], | ||||
|       ), | ||||
|       child: Autocomplete<UsersBasedOnSearchModel>( | ||||
|         optionsBuilder: (TextEditingValue textEditingValue) async { | ||||
|           if (textEditingValue.text.isEmpty) { | ||||
|             if (loading) { | ||||
|               setState(() { | ||||
|                 loading = false; | ||||
|               }); | ||||
|             } | ||||
|             return const Iterable<UsersBasedOnSearchModel>.empty(); | ||||
|           } | ||||
|           if (!loading) { | ||||
|             setState(() { | ||||
|               loading = true; | ||||
|             }); | ||||
|           } | ||||
|           List<UsersBasedOnSearchModel> workOrders = (await _TechnologyUsersProvider.getUsersBasedOnSearch(textEditingValue.text)); | ||||
|           setState(() { | ||||
|             loading = false; | ||||
|           }); | ||||
|           return workOrders; | ||||
|         }, | ||||
|         displayStringForOption: (UsersBasedOnSearchModel option) => widget.byName ? option.userName ?? "" : option.employeeId ?? "", | ||||
|         fieldViewBuilder: (BuildContext context, TextEditingController fieldTextEditingController, FocusNode fieldFocusNode, VoidCallback onFieldSubmitted) { | ||||
|           return TextField( | ||||
|             controller: _controller, | ||||
|             focusNode: fieldFocusNode, | ||||
|             style: AppTextStyles.bodyText.copyWith(color: AppColor.black10), | ||||
|             textAlign: TextAlign.start, | ||||
|             decoration: InputDecoration( | ||||
|               border: border, | ||||
|               disabledBorder: border, | ||||
|               focusedBorder: border, | ||||
|               enabledBorder: border, | ||||
|               errorBorder: border, | ||||
|               contentPadding: EdgeInsets.symmetric(vertical: 8.toScreenHeight, horizontal: 16.toScreenWidth), | ||||
|               constraints: const BoxConstraints(), | ||||
|               suffixIconConstraints: const BoxConstraints(maxHeight: 24, maxWidth: 24 + 8), | ||||
|               filled: true, | ||||
|               fillColor: AppColor.fieldBgColor(context), | ||||
|               errorStyle: AppTextStyle.tiny.copyWith(color: context.isDark ? AppColor.red50 : AppColor.red60), | ||||
|               floatingLabelStyle: AppTextStyle.body1.copyWith(fontWeight: FontWeight.w500, color: context.isDark ? null : AppColor.neutral20), | ||||
|               labelText: "Users going to use technology", | ||||
|               labelStyle: AppTextStyles.tinyFont.copyWith(color: AppColor.textColor(context)), | ||||
|               suffixIcon: loading ? const CircularProgressIndicator(color: AppColor.primary10, strokeWidth: 3.0).paddingOnly(end: 8) : null, | ||||
|             ), | ||||
|             textInputAction: TextInputAction.search, | ||||
|             onChanged: (text) { | ||||
|               fieldTextEditingController.text = text; | ||||
|             }, | ||||
|             onSubmitted: (String value) { | ||||
|               onFieldSubmitted(); | ||||
|             }, | ||||
|           ); | ||||
|         }, | ||||
|         onSelected: (UsersBasedOnSearchModel selection) { | ||||
|           if (widget.clearAfterPick) { | ||||
|             _controller.clear(); | ||||
|           } else { | ||||
|             _controller.text = widget.byName ? (selection.userName ?? "") : (selection.employeeId ?? ""); | ||||
|           } | ||||
|           widget.onPick(selection); | ||||
|         }, | ||||
|       ), | ||||
|     ); | ||||
|   } | ||||
| } | ||||
					Loading…
					
					
				
		Reference in New Issue