From 1e06449d8dfd3e3726a83a37ba9a94846d12bf62 Mon Sep 17 00:00:00 2001 From: nextwo <1234> Date: Tue, 7 Mar 2023 17:53:58 +0300 Subject: [PATCH] change Api structure for request gas refill page + solve null safety bugs faced it during restructure the code --- lib/api/gas_refill_api_client.dart | 94 ++++++++++ .../providers/api/gas_refill_provider.dart | 165 +++++------------- lib/controllers/validator/validator.dart | 2 +- .../user/gas_refill/gas_refill_details.dart | 6 +- .../user/gas_refill/request_gas_refill.dart | 47 ++--- .../user/gas_refill/track_gas_refill.dart | 12 +- 6 files changed, 157 insertions(+), 169 deletions(-) create mode 100644 lib/api/gas_refill_api_client.dart diff --git a/lib/api/gas_refill_api_client.dart b/lib/api/gas_refill_api_client.dart new file mode 100644 index 00000000..09352723 --- /dev/null +++ b/lib/api/gas_refill_api_client.dart @@ -0,0 +1,94 @@ +import 'dart:convert'; + +import 'package:test_sa/api/user_api_client.dart'; + +import '../controllers/api_routes/urls.dart'; +import '../models/gas_refill/gas_refill_model.dart'; +import 'api_client.dart'; + +class GasRefillApiClient{ + + static final GasRefillApiClient _instance =GasRefillApiClient._internal(); + + GasRefillApiClient._internal(); + + factory GasRefillApiClient() =>_instance; + + + Future> getRequestPages({ + required List items, + required int pageItemNumber + }) async { + + final response = await ApiClient().getJsonForResponse( + "${URLs.host1}${URLs.getGasRefill}",//body + headers: {"Content-Type": "application/json; charset=utf-8"}, + queryParameters: { + "uid":"${UserApiClient().user?.id}", + "token":"${UserApiClient().user?.token}", + "page":"${(items.length) ~/ pageItemNumber}", + } + ); + + // client's request was successfully received + List requestsListJson = json.decode(utf8.decode(response.bodyBytes)); + return requestsListJson.map((request) => GasRefillModel.fromJson(request)).toList(); + + } + + Future createModel({ + required GasRefillModel model, + }) async{ + + Map body = { + "uid": UserApiClient().user?.id.toString(), + "token": UserApiClient().user?.token ?? "", + "title": model.title ?? "", + "status": "0", //model.status.value.toString(), + }; + + body["details"] = jsonEncode(model.details + ?.map((model) => { + "type": model.type?.id.toString(), + "size": model.cylinderSize?.id.toString(), + "requsted_qty": model.requestedQuantity.toString(), + }) + .toList()); + + final response = await ApiClient().postJsonForResponse( + "${URLs.host1}${URLs.requestGasRefill}", + body, + ); + + return GasRefillModel.fromJson(json.decode(utf8.decode(response.bodyBytes))[0]); + + } + + Future updateModel({ + required GasRefillModel? oldModel, + required GasRefillModel newModel, + })async{ + Map body = { + "uid": UserApiClient().user?.id.toString(), + "token": UserApiClient().user?.token, + "title": newModel.title, + "status": newModel.status?.id.toString(), + }; + + body["details"] = jsonEncode(newModel.details + ?.map((model) => { + "type": model.type?.id.toString(), + "size": model.cylinderSize?.id.toString(), + "requsted_qty": model.requestedQuantity.toString(), + "deliverd_qty": model.deliveredQuantity.toString(), + }) + .toList()); + + final reponse = await ApiClient().postJsonForResponse( + "${URLs.host1}${URLs.updateGasRefill}/${newModel.id}", + body); + + oldModel?.fromGasRefillModel(newModel); + + } +} \ No newline at end of file diff --git a/lib/controllers/providers/api/gas_refill_provider.dart b/lib/controllers/providers/api/gas_refill_provider.dart index c6fa4e1f..0fb73f98 100644 --- a/lib/controllers/providers/api/gas_refill_provider.dart +++ b/lib/controllers/providers/api/gas_refill_provider.dart @@ -1,19 +1,25 @@ 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:test_sa/api/gas_refill_api_client.dart'; import '../../../models/gas_refill/gas_refill_model.dart'; import '../../../models/user.dart'; import '../../api_routes/urls.dart'; +import '../../http_status_manger/http_status_manger.dart'; +import '../../localization/localization.dart'; +import '../loading_notifier.dart'; -class GasRefillProvider extends ChangeNotifier { +class GasRefillProvider extends LoadingNotifier { // number of items call in each request final pageItemNumber = 50; //reset provider data void reset() { - items = null; + items.clear(); nextPage = true; stateCode = null; } @@ -27,134 +33,53 @@ class GasRefillProvider extends ChangeNotifier { bool nextPage = true; // list of user requests - List? items; - - // when requests in-process _loading = true - // done _loading = true - // failed _loading = false - bool? isLoading; - - /// return -2 if request in progress - /// return -1 if error happen when sending request - /// return state code if request complete may be 200, 404 or 403 - /// for more details check http state manager - /// lib\controllers\http_status_manger\http_status_manger.dart - Future getRequests({ - required String host, - required User user, - }) async { - if (isLoading == true) { - return -2; - } - isLoading = true; - Response response; - try { - response = await get( - Uri.parse("$host${URLs.getGasRefill}?uid=${user.id}" - "&token=${user.token}&page=${(items?.length ?? 0) ~/ pageItemNumber}"), - headers: {"Content-Type": "application/json; charset=utf-8"}); - stateCode = response.statusCode; - if (stateCode != null && stateCode! >= 200 && stateCode! < 300) { - // client's request was successfully received - List requestsListJson = json.decode(utf8.decode(response.bodyBytes)); - List itemsPage = requestsListJson.map((request) => GasRefillModel.fromJson(request)).toList(); - items ??= []; - items?.addAll(itemsPage); - if (itemsPage.length == pageItemNumber) { - nextPage = true; - } else { - nextPage = false; - } + List items=[]; + + Future getRequests() async { + waitApiRequest(() async { + items.addAll(await GasRefillApiClient().getRequestPages(items: items, pageItemNumber: pageItemNumber)); + if (items.length == pageItemNumber) { + nextPage = true; + } else { + nextPage = false; } - isLoading = false; - notifyListeners(); - return response.statusCode; - } catch (error) { - isLoading = false; - stateCode = -1; - notifyListeners(); - return -1; - } + }); } - Future createModel({ - required String host, - required User user, + Future createModel({ required GasRefillModel model, + required BuildContext context }) async { - Map body = { - "uid": user.id.toString(), - "token": user.token ?? "", - "title": model.title ?? "", - "status": "0", //model.status.value.toString(), - }; - - body["details"] = jsonEncode(model.details - ?.map((model) => { - "type": model.type?.id.toString(), - "size": model.cylinderSize?.id.toString(), - "requsted_qty": model.requestedQuantity.toString(), - }) - .toList()); - - Response response; - try { - response = await post( - Uri.parse(host + URLs.requestGasRefill), - body: body, - ); - - stateCode = response.statusCode; - if (response.statusCode >= 200 && response.statusCode < 300) { - final items = this.items; - if (items != null) { - items.insert(0, GasRefillModel.fromJson(json.decode(utf8.decode(response.bodyBytes))[0])); - notifyListeners(); - } + + final subtitle = AppLocalization.of(context)?.subtitle; + + waitApiRequest(() async { + items.insert(0, await GasRefillApiClient().createModel(model: model)); + notifyListeners(); + }, + onError: (error){ + String errorMessage = HttpStatusManger.getStatusMessage(status: error.error?.errorCode, subtitle: subtitle); + ScaffoldMessenger.of(context).showSnackBar(SnackBar( + content: Text(errorMessage), + )); + }, + onSuccess: (){ + Fluttertoast.showToast( + msg: subtitle?.requestCompleteSuccessfully ?? "", + ); + Navigator.of(context).pop(); } - return response.statusCode; - } catch (error) { - return -1; - } + ); + } - Future updateModel({ - required String host, - required User user, + Future updateModel({ required GasRefillModel? oldModel, required GasRefillModel newModel, }) async { - Map body = { - "uid": user.id.toString(), - "token": user.token, - "title": newModel.title ?? "", - "status": newModel.status?.id.toString(), - }; - - body["details"] = jsonEncode(newModel.details - ?.map((model) => { - "type": model.type?.id.toString(), - "size": model.cylinderSize?.id.toString(), - "requsted_qty": model.requestedQuantity.toString(), - "deliverd_qty": model.deliveredQuantity.toString(), - }) - .toList()); - - Response response; - try { - response = await post( - Uri.parse("$host${URLs.updateGasRefill}/${newModel.id}"), - body: body, - ); - - stateCode = response.statusCode; - if (response.statusCode >= 200 && response.statusCode < 300) { - oldModel?.fromGasRefillModel(newModel); - notifyListeners(); - } - return response.statusCode; - } catch (error) { - return -1; - } + + await GasRefillApiClient().updateModel(oldModel: oldModel, newModel: newModel); + + } } diff --git a/lib/controllers/validator/validator.dart b/lib/controllers/validator/validator.dart index bb84dfca..168ce897 100644 --- a/lib/controllers/validator/validator.dart +++ b/lib/controllers/validator/validator.dart @@ -36,7 +36,7 @@ class Validator { } // Return true if String is valid Numeric. Otherwise, return false - static bool isNumeric(String s) { + static bool isNumeric(String? s) { if (s == null) { return false; } diff --git a/lib/views/pages/user/gas_refill/gas_refill_details.dart b/lib/views/pages/user/gas_refill/gas_refill_details.dart index 22a09359..16f5fe50 100644 --- a/lib/views/pages/user/gas_refill/gas_refill_details.dart +++ b/lib/views/pages/user/gas_refill/gas_refill_details.dart @@ -36,8 +36,6 @@ class _GasRefillDetailsState extends State { final GasRefillModel _model = GasRefillModel(); bool _enableEdit = false; bool _validate = false; - UserProvider? _userProvider; - SettingProvider? _settingProvider; GasRefillProvider? _gasRefillProvider; bool _isLoading = false; Subtitle? _subtitle; @@ -53,7 +51,7 @@ class _GasRefillDetailsState extends State { _isLoading = true; setState(() {}); - int? status = await _gasRefillProvider?.updateModel(user: UserApiClient().user ?? User(), host: _settingProvider?.host ?? "", newModel: _model, oldModel: widget.model); + int? status = await _gasRefillProvider?.updateModel( newModel: _model, oldModel: widget.model); _isLoading = false; setState(() {}); if (status != null && status >= 200 && status < 300) { @@ -80,8 +78,6 @@ class _GasRefillDetailsState extends State { @override Widget build(BuildContext context) { _subtitle = AppLocalization.of(context)?.subtitle; - _userProvider = Provider.of(context); - _settingProvider = Provider.of(context); _gasRefillProvider = Provider.of(context); return Scaffold( key: _scaffoldKey, diff --git a/lib/views/pages/user/gas_refill/request_gas_refill.dart b/lib/views/pages/user/gas_refill/request_gas_refill.dart index 1de4d916..9488986b 100644 --- a/lib/views/pages/user/gas_refill/request_gas_refill.dart +++ b/lib/views/pages/user/gas_refill/request_gas_refill.dart @@ -33,8 +33,6 @@ class _RequestGasRefillState extends State { bool _isLoading = false; bool _validate = false; Subtitle? _subtitle; - UserProvider? _userProvider; - SettingProvider? _settingProvider; GasRefillProvider? _gasRefillProvider; GasRefillDetails _currentDetails = GasRefillDetails(model: null); final TextEditingController _requestedQuantityController = TextEditingController(); @@ -48,33 +46,6 @@ class _RequestGasRefillState extends State { if (mounted) super.setState(() {}); } - _onSubmit() async { - if ((_formModel.details?.isEmpty ?? false)) { - if (!_addNewModel()) return; - } - - _isLoading = true; - setState(() {}); - - int? status = await _gasRefillProvider?.createModel( - user: UserApiClient().user ?? User(), - host: _settingProvider?.host ?? "", - model: _formModel, - ); - _isLoading = false; - setState(() {}); - if (status != null && status >= 200 && status < 300) { - Fluttertoast.showToast( - msg: _subtitle?.requestCompleteSuccessfully ?? "", - ); - Navigator.of(context).pop(); - } else { - String errorMessage = HttpStatusManger.getStatusMessage(status: status, subtitle: _subtitle); - ScaffoldMessenger.of(context).showSnackBar(SnackBar( - content: Text(errorMessage), - )); - } - } bool _addNewModel() { _validate = true; @@ -106,8 +77,6 @@ class _RequestGasRefillState extends State { @override Widget build(BuildContext context) { _subtitle = AppLocalization.of(context)?.subtitle; - _userProvider = Provider.of(context); - _settingProvider = Provider.of(context); _gasRefillProvider = Provider.of(context, listen: false); return Scaffold( key: _scaffoldKey, @@ -203,11 +172,11 @@ class _RequestGasRefillState extends State { height: 4, ), ATextFormField( - initialValue: (_currentDetails?.requestedQuantity ?? "").toString(), + initialValue: (_currentDetails.requestedQuantity??"").toString(), textAlign: TextAlign.center, controller: _requestedQuantityController, style: Theme.of(context).textTheme.subtitle1, - validator: (value) => Validator.isNumeric(value!) ? '' : "allow numbers only", + validator: (value) => Validator.isNumeric(value) ? null : "allow numbers only", textInputType: TextInputType.number, onSaved: (value) { _currentDetails.requestedQuantity = int.tryParse(value!); @@ -237,7 +206,17 @@ class _RequestGasRefillState extends State { const SizedBox(height: 16), AButton( text: _subtitle?.submit ?? "", - onPressed: _onSubmit, + onPressed: () async { + if ((_formModel.details?.isEmpty ?? false)) { + if (!_addNewModel()) return; + } + + await _gasRefillProvider?.createModel( + model: _formModel, + context: context + ); + + }, ), const SizedBox( height: 100, diff --git a/lib/views/pages/user/gas_refill/track_gas_refill.dart b/lib/views/pages/user/gas_refill/track_gas_refill.dart index d70f7608..2e9968cd 100644 --- a/lib/views/pages/user/gas_refill/track_gas_refill.dart +++ b/lib/views/pages/user/gas_refill/track_gas_refill.dart @@ -36,15 +36,12 @@ class _TrackGasRefillPageState extends State with TickerProv return Scaffold( body: SafeArea( child: LoadingManager( - isLoading: _gasRefillProvider?.isLoading, + isLoading: _gasRefillProvider?.loading, isFailedLoading: _gasRefillProvider?.items == null, stateCode: _gasRefillProvider?.stateCode, onRefresh: () async { _gasRefillProvider?.reset(); - await _gasRefillProvider?.getRequests( - user: UserApiClient().user ?? User(), - host: _settingProvider?.host ?? "", - ); + await _gasRefillProvider?.getRequests(); }, child: Stack( children: [ @@ -78,10 +75,7 @@ class _TrackGasRefillPageState extends State with TickerProv child: GasRefillList( nextPage: _gasRefillProvider?.nextPage ?? false, onLazyLoad: () async { - await _gasRefillProvider?.getRequests( - user: UserApiClient().user ?? User(), - host: _settingProvider?.host ?? "", - ); + await _gasRefillProvider?.getRequests(); }, items: _gasRefillProvider?.items ?? [], ),