From 3bdae42769fb20f65f165c15896fa137a5698c1b Mon Sep 17 00:00:00 2001 From: zaid_daoud Date: Thu, 12 Oct 2023 16:00:06 +0300 Subject: [PATCH] 1- change text form field code 2- app bar design 3- working on request gas refill screen --- assets/translations/ar.json | 7 +- assets/translations/en.json | 7 +- lib/main.dart | 6 + lib/models/base.dart | 5 + lib/models/enums/translation_keys.dart | 5 + lib/models/lookup.dart | 33 +---- .../app_floating_action_button.dart | 40 ++--- .../common_widgets/app_lazy_loading.dart | 12 +- .../common_widgets/app_loading_manager.dart | 94 ++++++++++++ .../common_widgets/app_text_form_field.dart | 90 +++++------- .../single_item_drop_down_menu.dart | 139 ++++++++++++++++++ .../pages/new_gas_refill_request_page.dart | 37 +++++ .../cylinder_size_provider.dart | 34 +++++ .../cylinder_type_provider.dart | 34 +++++ .../gas_types_provider.dart | 34 +++++ lib/providers/loading_list_notifier.dart | 25 ++++ .../create_sub_workorder_page.dart | 2 +- .../user/gas_refill/request_gas_refill.dart | 4 +- 18 files changed, 501 insertions(+), 107 deletions(-) create mode 100644 lib/models/base.dart create mode 100644 lib/new_views/common_widgets/app_loading_manager.dart create mode 100644 lib/new_views/common_widgets/single_item_drop_down_menu.dart create mode 100644 lib/providers/gas_request_providers/cylinder_size_provider.dart create mode 100644 lib/providers/gas_request_providers/cylinder_type_provider.dart create mode 100644 lib/providers/gas_request_providers/gas_types_provider.dart create mode 100644 lib/providers/loading_list_notifier.dart diff --git a/assets/translations/ar.json b/assets/translations/ar.json index 7fd3ace3..44682580 100644 --- a/assets/translations/ar.json +++ b/assets/translations/ar.json @@ -20,5 +20,10 @@ "newServiceRequest" : "طلب خدمة جديدة", "newGasRefillRequest" : "طلب إعادة تعبئة غاز جديد", "newTransferRequest" : "طلب نقل جديد", - "submitRequest" : "تأكيد الطلب" + "submitRequest" : "تأكيد الطلب", + "select" : "إختر", + "gasType" : "نوع الغاز", + "quantity" : "الكمية", + "cylinderType" : "نوع الأسطوانة", + "cylinderSize" : "حجم الأسطوانة" } \ No newline at end of file diff --git a/assets/translations/en.json b/assets/translations/en.json index 1a3089c4..7ade24cb 100644 --- a/assets/translations/en.json +++ b/assets/translations/en.json @@ -20,5 +20,10 @@ "newServiceRequest" : "New Service Request", "newGasRefillRequest" : "New Gas Refill Request", "newTransferRequest" : "New Transfer Request", - "submitRequest" : "Submit Request" + "submitRequest" : "Submit Request", + "select" : "Select", + "gasType": "Gas Type", + "quantity" : "Quantity", + "cylinderType" : "Cylinder Type", + "cylinderSize" : "Cylinder Size" } \ No newline at end of file diff --git a/lib/main.dart b/lib/main.dart index 93a4b750..d592e61e 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -12,6 +12,9 @@ import 'package:test_sa/new_views/pages/login_page.dart'; import 'package:test_sa/new_views/pages/new_service_request_page.dart'; import 'package:test_sa/new_views/pages/new_transfer_request_page.dart'; import 'package:test_sa/new_views/pages/splash_page.dart'; +import 'package:test_sa/providers/gas_request_providers/cylinder_size_provider.dart'; +import 'package:test_sa/providers/gas_request_providers/cylinder_type_provider.dart'; +import 'package:test_sa/providers/gas_request_providers/gas_types_provider.dart'; import 'controllers/providers/api/user_provider.dart'; import 'controllers/providers/settings/setting_provider.dart'; @@ -52,6 +55,9 @@ class MyApp extends StatelessWidget { return MultiProvider( providers: [ ChangeNotifierProvider(create: (_) => UserProvider()), + ChangeNotifierProvider(create: (_) => GasTypesProvider()), + ChangeNotifierProvider(create: (_) => CylinderTypesProvider()), + ChangeNotifierProvider(create: (_) => CylinderSizeProvider()), ], child: GestureDetector( onTap: () { diff --git a/lib/models/base.dart b/lib/models/base.dart new file mode 100644 index 00000000..7a12740f --- /dev/null +++ b/lib/models/base.dart @@ -0,0 +1,5 @@ +class Base { + final String name, identifier; + + const Base({this.name, this.identifier}); +} diff --git a/lib/models/enums/translation_keys.dart b/lib/models/enums/translation_keys.dart index dff1a9af..c4a099f7 100644 --- a/lib/models/enums/translation_keys.dart +++ b/lib/models/enums/translation_keys.dart @@ -21,4 +21,9 @@ enum TranslationKeys { newGasRefillRequest, newTransferRequest, submitRequest, + select, + gasType, + quantity, + cylinderType, + cylinderSize, } diff --git a/lib/models/lookup.dart b/lib/models/lookup.dart index e4deb993..8080a79b 100644 --- a/lib/models/lookup.dart +++ b/lib/models/lookup.dart @@ -1,15 +1,9 @@ -class Lookup { - //old name label - final String name; - // old name key - final int value; - final int id; +import 'base.dart'; - const Lookup({ - this.name, - this.value, - this.id, - }); +class Lookup extends Base { + final int id, value; + + Lookup({this.id, this.value, String name}) : super(identifier: id?.toString(), name: name); @override bool operator ==(Object other) => identical(this, other) || other is Lookup && ((value != null && value == other.value) || (id != null && id == other.id)); @@ -38,21 +32,4 @@ class Lookup { value: parsedJson["value"], ); } - -// factory Lookup.fromJson(Map parsedJson){ -// if(parsedJson["id"] == null && parsedJson["uid"] == null) return null; -// return Lookup( -// name: parsedJson["value"], -// id: parsedJson["id"] is int -// ? parsedJson["id"] -// : int.tryParse(parsedJson["id"] ?? parsedJson["uid"]), -// ); -// } - -// factory Lookup.fromIntIdJson(Map parsedJson){ -// return Lookup( -// name: parsedJson["value"], -// id: parsedJson["id"], -// ); -// } } diff --git a/lib/new_views/common_widgets/app_floating_action_button.dart b/lib/new_views/common_widgets/app_floating_action_button.dart index d8c6617f..09339a50 100644 --- a/lib/new_views/common_widgets/app_floating_action_button.dart +++ b/lib/new_views/common_widgets/app_floating_action_button.dart @@ -35,24 +35,30 @@ class _AppFloatingActionButtonState extends State { return Column( mainAxisAlignment: MainAxisAlignment.end, crossAxisAlignment: CrossAxisAlignment.end, + mainAxisSize: MainAxisSize.min, children: [ - AnimatedOpacity( - opacity: turns != 0 ? 1 : 0, - duration: duration, - child: Card( - shape: Theme.of(context).cardTheme.copyWith().shape, - margin: EdgeInsetsDirectional.only(start: 60.toScreenWidth), - child: Padding( - padding: EdgeInsets.symmetric(vertical: 8.toScreenHeight), - child: Column( - mainAxisSize: MainAxisSize.min, - children: [ - const _FloatingButtonListTile(iconName: "gas_refill_request", label: TranslationKeys.gasRefillRequest, routeName: NewGasRefillRequestPage.routeName), - Padding(padding: EdgeInsets.symmetric(horizontal: 16.toScreenWidth), child: const Divider()), - const _FloatingButtonListTile(iconName: "transfer_request", label: TranslationKeys.transferRequest, routeName: NewTransferRequestPage.routeName), - Padding(padding: EdgeInsets.symmetric(horizontal: 16.toScreenWidth), child: const Divider()), - const _FloatingButtonListTile(iconName: "service_request", label: TranslationKeys.serviceRequest, routeName: NewServiceRequestPage.routeName), - ], + Visibility( + visible: turns != 0, + maintainAnimation: true, + maintainState: true, + child: AnimatedOpacity( + opacity: turns != 0 ? 1 : 0, + duration: duration, + child: Card( + shape: Theme.of(context).cardTheme.copyWith().shape, + margin: EdgeInsetsDirectional.only(start: 60.toScreenWidth), + child: Padding( + padding: EdgeInsets.symmetric(vertical: 8.toScreenHeight), + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + const _FloatingButtonListTile(iconName: "gas_refill_request", label: TranslationKeys.gasRefillRequest, routeName: NewGasRefillRequestPage.routeName), + Padding(padding: EdgeInsets.symmetric(horizontal: 16.toScreenWidth), child: const Divider()), + const _FloatingButtonListTile(iconName: "transfer_request", label: TranslationKeys.transferRequest, routeName: NewTransferRequestPage.routeName), + Padding(padding: EdgeInsets.symmetric(horizontal: 16.toScreenWidth), child: const Divider()), + const _FloatingButtonListTile(iconName: "service_request", label: TranslationKeys.serviceRequest, routeName: NewServiceRequestPage.routeName), + ], + ), ), ), ), diff --git a/lib/new_views/common_widgets/app_lazy_loading.dart b/lib/new_views/common_widgets/app_lazy_loading.dart index 19b001c4..ecfb4806 100644 --- a/lib/new_views/common_widgets/app_lazy_loading.dart +++ b/lib/new_views/common_widgets/app_lazy_loading.dart @@ -1,8 +1,8 @@ import 'package:flutter/material.dart'; +import 'package:test_sa/extensions/int_extensions.dart'; +import 'package:test_sa/new_views/app_style/app_color.dart'; import 'package:test_sa/views/app_style/sizing.dart'; -import '../../views/widgets/loaders/app_loading.dart'; - class AppLazyLoading extends StatelessWidget { const AppLazyLoading({Key key}) : super(key: key); @@ -10,11 +10,11 @@ class AppLazyLoading extends StatelessWidget { Widget build(BuildContext context) { return Center( child: Container( - height: 36 * AppStyle.getScaleFactor(context), - width: 36 * AppStyle.getScaleFactor(context), + height: 36.toScreenWidth, + width: 36.toScreenWidth, padding: const EdgeInsets.all(8), - decoration: const BoxDecoration(color: Colors.white, shape: BoxShape.circle, boxShadow: [AppStyle.boxShadow]), - child: const ALoading(), + decoration: const BoxDecoration(color: AppColor.neutral10, shape: BoxShape.circle, boxShadow: [AppStyle.boxShadow]), + child: const Center(child: CircularProgressIndicator(strokeWidth: 3)), ), ); } diff --git a/lib/new_views/common_widgets/app_loading_manager.dart b/lib/new_views/common_widgets/app_loading_manager.dart new file mode 100644 index 00000000..f29fef1e --- /dev/null +++ b/lib/new_views/common_widgets/app_loading_manager.dart @@ -0,0 +1,94 @@ +import 'package:flutter/material.dart'; +import 'package:test_sa/extensions/context_extension.dart'; +import 'package:test_sa/extensions/int_extensions.dart'; +import 'package:test_sa/new_views/common_widgets/app_lazy_loading.dart'; + +import '../app_style/app_color.dart'; + +class AppLoadingManager extends StatefulWidget { + final bool isLoading; + final bool isFailedLoading; + final bool isNotPage; + final int progress; + final bool askOnBack; + final int stateCode; + final Future Function() onRefresh; + final Widget child; + + const AppLoadingManager({ + Key key, + @required this.isLoading, + @required this.isFailedLoading, + @required this.stateCode, + @required this.onRefresh, + @required this.child, + this.progress, + this.isNotPage = false, + this.askOnBack = false, + }) : super(key: key); + + @override + State createState() => _AppLoadingManagerState(); +} + +class _AppLoadingManagerState extends State { + @override + void initState() { + if (widget.onRefresh != null && widget.stateCode == null) { + WidgetsBinding.instance.addPostFrameCallback((timeStamp) { + widget.onRefresh(); + }); + } + super.initState(); + } + + @override + Widget build(BuildContext context) { + Widget placeHolder; + // to load data if load not start + if (widget.isLoading != true && widget.stateCode == null) { + WidgetsBinding.instance.addPostFrameCallback((timeStamp) { + widget.onRefresh(); + }); + } + + // if loading of still not start in loading (true or null) + // return loading widget + if (widget.isLoading != false || widget.stateCode == null) { + placeHolder = Container( + height: 60.toScreenHeight, + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(10), + color: context.isDark ? AppColor.neutral50 : Colors.white, + ), + child: const AppLazyLoading(), + ); + } else if (widget.isFailedLoading && !widget.isNotPage) { + // if failed return failed widget + placeHolder = Center( + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text("Error Request Failed", style: Theme.of(context).textTheme.titleMedium), + 16.height, + OutlinedButton( + onPressed: widget.onRefresh, + child: const Text("try again"), + ) + ], + ), + ); + } + + // if load end successfully return loaded widget + return RefreshIndicator( + onRefresh: () async { + await widget.onRefresh(); + }, + child: AnimatedSwitcher( + duration: const Duration(milliseconds: 400), + child: placeHolder ?? widget.child, + ), + ); + } +} diff --git a/lib/new_views/common_widgets/app_text_form_field.dart b/lib/new_views/common_widgets/app_text_form_field.dart index e3d4e24d..48f98765 100644 --- a/lib/new_views/common_widgets/app_text_form_field.dart +++ b/lib/new_views/common_widgets/app_text_form_field.dart @@ -62,57 +62,45 @@ class _AppTextFormFieldState extends State { @override Widget build(BuildContext context) { - return Stack( - alignment: Alignment.topCenter, - children: [ - Container( - height: widget.textInputType == TextInputType.multiline ? null : 56.toScreenHeight, - decoration: BoxDecoration( - color: context.isDark ? AppColor.neutral50 : Colors.white, - borderRadius: BorderRadius.circular(10), - boxShadow: [BoxShadow(color: Colors.black.withOpacity(0.05), blurRadius: 10)], - ), - ), - Padding( - padding: EdgeInsets.symmetric(horizontal: 16.toScreenWidth), - child: TextFormField( - focusNode: widget.node, - enabled: widget.enable, - onSaved: widget.onSaved, - initialValue: widget.controller != null ? null : widget.initialValue, - validator: widget.validator, - onChanged: widget.onChange, - obscureText: widget.obscureText ?? false, - keyboardType: widget.textInputType, - maxLines: widget.textInputType == TextInputType.multiline ? null : 1, - obscuringCharacter: "*", - controller: widget.controller, - textInputAction: widget.textInputType == TextInputType.multiline ? null : widget.textInputAction ?? TextInputAction.next, - onEditingComplete: widget.onAction ?? () => FocusScope.of(context).nextFocus(), - style: Theme.of(context).textTheme.bodyLarge, - decoration: InputDecoration( - border: InputBorder.none, - suffixIconConstraints: const BoxConstraints(minWidth: 0), - disabledBorder: InputBorder.none, - focusedBorder: InputBorder.none, - enabledBorder: InputBorder.none, - contentPadding: EdgeInsets.zero, - constraints: const BoxConstraints(), - errorStyle: Theme.of(context).textTheme.bodySmall?.copyWith(color: context.isDark ? AppColor.red50 : AppColor.red60, height: 0.7), - floatingLabelStyle: Theme.of(context).textTheme.labelLarge?.copyWith(color: context.isDark ? null : AppColor.neutral20, fontWeight: FontWeight.w500), - hintText: widget.hintText != null ? context.translate(widget.hintText) : null, - labelText: widget.labelText != null ? context.translate(widget.labelText) : null, - suffixIcon: widget.prefixIconData == null - ? null - : Icon( - widget.prefixIconData, - size: widget.prefixIconSize == null ? 20 * AppStyle.getScaleFactor(context) : (widget.prefixIconSize - 10) * AppStyle.getScaleFactor(context), - color: const Color(0xff2e303a), - ), - ), - ), - ), - ], + final border = UnderlineInputBorder(borderSide: BorderSide.none, borderRadius: BorderRadius.circular(10)); + return TextFormField( + focusNode: widget.node, + enabled: widget.enable, + onSaved: widget.onSaved, + initialValue: widget.controller != null ? null : widget.initialValue, + validator: widget.validator, + onChanged: widget.onChange, + obscureText: widget.obscureText ?? false, + keyboardType: widget.textInputType, + maxLines: widget.textInputType == TextInputType.multiline ? null : 1, + obscuringCharacter: "*", + controller: widget.controller, + textInputAction: widget.textInputType == TextInputType.multiline ? null : widget.textInputAction ?? TextInputAction.next, + onEditingComplete: widget.onAction ?? () => FocusScope.of(context).nextFocus(), + style: Theme.of(context).textTheme.bodyLarge, + 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(minWidth: 0), + filled: true, + fillColor: context.isDark ? AppColor.neutral50 : Colors.white, + errorStyle: Theme.of(context).textTheme.bodySmall?.copyWith(color: context.isDark ? AppColor.red50 : AppColor.red60), + floatingLabelStyle: Theme.of(context).textTheme.labelLarge?.copyWith(color: context.isDark ? null : AppColor.neutral20, fontWeight: FontWeight.w500), + hintText: widget.hintText != null ? context.translate(widget.hintText) : null, + labelText: widget.labelText != null ? context.translate(widget.labelText) : null, + suffixIcon: widget.prefixIconData == null + ? null + : Icon( + widget.prefixIconData, + size: widget.prefixIconSize == null ? 20 * AppStyle.getScaleFactor(context) : (widget.prefixIconSize - 10) * AppStyle.getScaleFactor(context), + color: AppColor.neutral70, + ), + ), ); } } diff --git a/lib/new_views/common_widgets/single_item_drop_down_menu.dart b/lib/new_views/common_widgets/single_item_drop_down_menu.dart new file mode 100644 index 00000000..5bc9f5c7 --- /dev/null +++ b/lib/new_views/common_widgets/single_item_drop_down_menu.dart @@ -0,0 +1,139 @@ +import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; +import 'package:test_sa/extensions/context_extension.dart'; +import 'package:test_sa/extensions/int_extensions.dart'; +import 'package:test_sa/models/enums/translation_keys.dart'; +import 'package:test_sa/new_views/common_widgets/app_loading_manager.dart'; +import 'package:test_sa/providers/loading_list_notifier.dart'; + +import '../../models/base.dart'; +import '../app_style/app_color.dart'; + +class SingleItemDropDownMenu extends StatefulWidget { + final BuildContext context; + final Function(T) onSelect; + final T initialValue; + final bool enabled; + final TranslationKeys title; + const SingleItemDropDownMenu({Key key, @required this.context, @required this.title, this.onSelect, this.initialValue, this.enabled = true}) : super(key: key); + + @override + State> createState() => _SingleItemDropDownMenuState(); +} + +class _SingleItemDropDownMenuState extends State> { + T _selectedItem; + X provider; + + @override + void initState() { + provider = Provider.of(widget.context); + if (widget.initialValue != null) { + final result = provider.items?.where((element) { + return element == widget.initialValue; + }); + if (result.isNotEmpty) _selectedItem = result.first; + if (widget.initialValue?.identifier ?? "" != _selectedItem?.identifier ?? "") { + widget.onSelect(_selectedItem); + } + } + + super.initState(); + } + + @override + void setState(VoidCallback fn) { + if (mounted) super.setState(fn); + } + + @override + void didUpdateWidget(covariant SingleItemDropDownMenu oldWidget) { + if (widget.initialValue != null) { + final result = provider.items?.where((element) { + return element == widget.initialValue; + }); + if (result.isNotEmpty) { + _selectedItem = result.first; + } else { + _selectedItem = null; + } + if (widget.initialValue?.identifier ?? "" != _selectedItem?.identifier ?? "") { + widget.onSelect(_selectedItem); + } + } else { + _selectedItem = null; + } + super.didUpdateWidget(oldWidget); + } + + @override + Widget build(BuildContext context) { + return AppLoadingManager( + isLoading: provider.loading, + isFailedLoading: provider.items == null, + stateCode: provider.stateCode, + onRefresh: () async { + provider.reset(); + await provider.getDate(); + }, + child: Container( + height: 60.toScreenHeight, + padding: EdgeInsets.symmetric(horizontal: 16.toScreenWidth), + decoration: BoxDecoration( + color: context.isDark ? AppColor.neutral50 : Colors.white, + borderRadius: BorderRadius.circular(10), + boxShadow: [BoxShadow(color: Colors.black.withOpacity(0.05), blurRadius: 10)], + ), + child: Stack( + alignment: Alignment.center, + children: [ + const PositionedDirectional(end: 0, child: Icon(Icons.keyboard_arrow_down_rounded)), + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text( + context.translate(widget.title), + style: Theme.of(context).textTheme.bodySmall?.copyWith(color: context.isDark ? null : AppColor.neutral20, fontWeight: FontWeight.w500), + ), + DropdownButton( + value: _selectedItem, + iconSize: 24, + isDense: true, + icon: const SizedBox.shrink(), + elevation: 0, + isExpanded: true, + hint: Text( + context.translate(TranslationKeys.select), + style: Theme.of(context).textTheme.bodyLarge, + ), + style: TextStyle(color: Theme.of(context).primaryColor), + underline: const SizedBox.shrink(), + onChanged: widget.enabled == false + ? null + : (T newValue) { + setState(() { + _selectedItem = newValue; + }); + widget.onSelect(newValue); + }, + items: provider.items?.map>((value) { + return DropdownMenuItem( + value: value, + child: Text( + value?.name ?? "", + style: Theme.of(context).textTheme.bodyLarge, + ), + ); + })?.toList(), + ), + ], + ), + ), + ], + ), + ), + ); + } +} diff --git a/lib/new_views/pages/new_gas_refill_request_page.dart b/lib/new_views/pages/new_gas_refill_request_page.dart index e2aa038d..58e9a7ff 100644 --- a/lib/new_views/pages/new_gas_refill_request_page.dart +++ b/lib/new_views/pages/new_gas_refill_request_page.dart @@ -1,6 +1,13 @@ import 'package:flutter/material.dart'; +import 'package:test_sa/extensions/int_extensions.dart'; import 'package:test_sa/models/enums/translation_keys.dart'; +import 'package:test_sa/models/lookup.dart'; import 'package:test_sa/new_views/common_widgets/app_filled_button.dart'; +import 'package:test_sa/new_views/common_widgets/app_text_form_field.dart'; +import 'package:test_sa/new_views/common_widgets/single_item_drop_down_menu.dart'; +import 'package:test_sa/providers/gas_request_providers/cylinder_size_provider.dart'; +import 'package:test_sa/providers/gas_request_providers/cylinder_type_provider.dart'; +import 'package:test_sa/providers/gas_request_providers/gas_types_provider.dart'; import '../common_widgets/default_app_bar.dart'; @@ -12,6 +19,36 @@ class NewGasRefillRequestPage extends StatelessWidget { Widget build(BuildContext context) { return Scaffold( appBar: const DefaultAppBar(title: TranslationKeys.newGasRefillRequest), + body: Padding( + padding: EdgeInsets.symmetric(horizontal: 16.toScreenWidth), + child: SingleChildScrollView( + child: Column( + children: [ + 16.height, + SingleItemDropDownMenu( + context: context, + title: TranslationKeys.gasType, + ), + 8.height, + const AppTextFormField( + labelText: TranslationKeys.quantity, + textInputType: TextInputType.number, + ), + 8.height, + SingleItemDropDownMenu( + context: context, + title: TranslationKeys.cylinderType, + ), + 8.height, + SingleItemDropDownMenu( + context: context, + title: TranslationKeys.cylinderSize, + ), + 8.height, + ], + ), + ), + ), floatingActionButtonLocation: FloatingActionButtonLocation.centerDocked, floatingActionButton: AppFilledButton( label: TranslationKeys.submitRequest, diff --git a/lib/providers/gas_request_providers/cylinder_size_provider.dart b/lib/providers/gas_request_providers/cylinder_size_provider.dart new file mode 100644 index 00000000..7f6a574b --- /dev/null +++ b/lib/providers/gas_request_providers/cylinder_size_provider.dart @@ -0,0 +1,34 @@ +import 'dart:convert'; + +import 'package:http/http.dart'; + +import '../../controllers/api_routes/api_manager.dart'; +import '../../controllers/api_routes/urls.dart'; +import '../../models/lookup.dart'; +import '../loading_list_notifier.dart'; + +class CylinderSizeProvider extends LoadingListNotifier { + @override + Future getDate() async { + if (loading ?? false) return -2; + loading = true; + notifyListeners(); + try { + Response response = await ApiManager.instance.get(URLs.getGasTypes); + stateCode = response.statusCode; + if (response.statusCode >= 200 && response.statusCode < 300) { + // client's request was successfully received + List categoriesListJson = json.decode(response.body)["data"]; + items = categoriesListJson.map((item) => Lookup.fromJson(item)).toList(); + } + loading = false; + notifyListeners(); + return response.statusCode; + } catch (error) { + loading = false; + stateCode = -1; + notifyListeners(); + return -1; + } + } +} diff --git a/lib/providers/gas_request_providers/cylinder_type_provider.dart b/lib/providers/gas_request_providers/cylinder_type_provider.dart new file mode 100644 index 00000000..165c0dd9 --- /dev/null +++ b/lib/providers/gas_request_providers/cylinder_type_provider.dart @@ -0,0 +1,34 @@ +import 'dart:convert'; + +import 'package:http/http.dart'; + +import '../../controllers/api_routes/api_manager.dart'; +import '../../controllers/api_routes/urls.dart'; +import '../../models/lookup.dart'; +import '../loading_list_notifier.dart'; + +class CylinderTypesProvider extends LoadingListNotifier { + @override + Future getDate() async { + if (loading ?? false) return -2; + loading = true; + notifyListeners(); + try { + Response response = await ApiManager.instance.get(URLs.getGasTypes); + stateCode = response.statusCode; + if (response.statusCode >= 200 && response.statusCode < 300) { + // client's request was successfully received + List categoriesListJson = json.decode(response.body)["data"]; + items = categoriesListJson.map((item) => Lookup.fromJson(item)).toList(); + } + loading = false; + notifyListeners(); + return response.statusCode; + } catch (error) { + loading = false; + stateCode = -1; + notifyListeners(); + return -1; + } + } +} diff --git a/lib/providers/gas_request_providers/gas_types_provider.dart b/lib/providers/gas_request_providers/gas_types_provider.dart new file mode 100644 index 00000000..1e18fcf5 --- /dev/null +++ b/lib/providers/gas_request_providers/gas_types_provider.dart @@ -0,0 +1,34 @@ +import 'dart:convert'; + +import 'package:http/http.dart'; +import 'package:test_sa/models/lookup.dart'; +import 'package:test_sa/providers/loading_list_notifier.dart'; + +import '../../controllers/api_routes/api_manager.dart'; +import '../../controllers/api_routes/urls.dart'; + +class GasTypesProvider extends LoadingListNotifier { + @override + Future getDate() async { + if (loading ?? false) return -2; + loading = true; + notifyListeners(); + try { + Response response = await ApiManager.instance.get(URLs.getGasTypes); + stateCode = response.statusCode; + if (response.statusCode >= 200 && response.statusCode < 300) { + // client's request was successfully received + List categoriesListJson = json.decode(response.body)["data"]; + items = categoriesListJson.map((item) => Lookup.fromJson(item)).toList(); + } + loading = false; + notifyListeners(); + return response.statusCode; + } catch (error) { + loading = false; + stateCode = -1; + notifyListeners(); + return -1; + } + } +} diff --git a/lib/providers/loading_list_notifier.dart b/lib/providers/loading_list_notifier.dart new file mode 100644 index 00000000..8698287d --- /dev/null +++ b/lib/providers/loading_list_notifier.dart @@ -0,0 +1,25 @@ +import 'package:flutter/material.dart'; +import 'package:test_sa/models/base.dart'; + +abstract class LoadingListNotifier extends ChangeNotifier { + int stateCode; + + List items = []; + + bool _loading = false; + + bool get loading => _loading; + + set loading(bool value) { + _loading = value; + notifyListeners(); + } + + void reset() { + items = null; + _loading = null; + stateCode = null; + } + + Future getDate(); +} 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 6e4df099..ce67949b 100644 --- a/lib/views/pages/sub_workorder/create_sub_workorder_page.dart +++ b/lib/views/pages/sub_workorder/create_sub_workorder_page.dart @@ -45,7 +45,7 @@ class CreateSubWorkOrderPage extends StatefulWidget { class _CreateSubWorkOrderPageState extends State { final GlobalKey _formKey = GlobalKey(); SearchWorkOrder _subWorkOrders; - Lookup _serviceReportReason = const Lookup(); + Lookup _serviceReportReason = Lookup(); ServiceReport _serviceReport; final List _files = []; bool _isLoading = false; 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 8228da29..52c4c9dc 100644 --- a/lib/views/pages/user/gas_refill/request_gas_refill.dart +++ b/lib/views/pages/user/gas_refill/request_gas_refill.dart @@ -162,7 +162,7 @@ class _RequestGasRefillState extends State { if (_firstTime) { String _clientName; if (widget.gasRefillModel != null) { - _formModel.status = widget.gasRefillModel?.status ?? const Lookup(value: 0); + _formModel.status = widget.gasRefillModel?.status ?? Lookup(value: 0); _gasRefillProvider.expectedDateTime = _formModel.expectedDate; _gasRefillProvider.timer = TimerModel(startAt: widget.gasRefillModel?.startDate, endAt: widget.gasRefillModel?.endDate); _clientName = _formModel.clientName; @@ -229,7 +229,7 @@ class _RequestGasRefillState extends State { height: 4, ), GasStatusMenu( - initialValue: _formModel.status ?? const Lookup(value: 0), + initialValue: _formModel.status ?? Lookup(value: 0), enabled: widget.gasRefillModel != null, onSelect: (status) { _formModel.status = status;