From 34b669eea0501157604dd0b20cbbe7b5f98cc4e8 Mon Sep 17 00:00:00 2001 From: suvaysov Date: Tue, 28 Jun 2022 16:13:59 +0600 Subject: [PATCH] dictionaries --- README.md | 17 +- assets/images/svg/ostatki.svg | 12 + lib/core/base/base_service.dart | 6 +- lib/core/models/dialog_models.dart | 1 - .../models/dictionary/category_response.dart | 5 +- .../contragent_response_entity.dart | 29 +++ .../contragent_response_entity.g.dart | 32 +++ lib/core/models/dictionary/good_response.dart | 9 +- .../response/dict_response_entity.dart | 62 +++++ .../response/dict_response_entity.g.dart | 53 ++++ lib/core/models/flow/dao/transaction_dao.dart | 1 - .../flow/sell_return/sell_return_request.dart | 8 +- .../sell_return/sell_return_request.g.dart | 11 +- lib/core/models/response.dart | 34 --- lib/core/models/settings/printer_setting.dart | 56 ++--- lib/core/models/ui_dao/popup_item_dao.dart | 1 - lib/core/redux/actions/journal_actions.dart | 10 +- lib/core/redux/actions/nav_actions.dart | 2 +- lib/core/redux/actions/setting_actions.dart | 15 -- lib/core/redux/actions/user_actions.dart | 2 +- lib/core/redux/reducers/journal_reducer.dart | 4 - lib/core/redux/reducers/nav_reducer.dart | 2 - lib/core/redux/reducers/sell_reducer.dart | 2 - lib/core/redux/reducers/setting_reducer.dart | 6 - lib/core/redux/state/nav_state.dart | 4 +- lib/core/redux/state/sell_state.dart | 21 +- lib/core/redux/state/setting_state.dart | 19 +- lib/core/redux/state/user_state.dart | 18 +- lib/core/redux/store.dart | 3 +- lib/core/services/api_service.dart | 56 +++-- lib/core/services/data_service.dart | 2 - lib/core/services/db_service.dart | 4 +- lib/core/services/dialog_service.dart | 3 +- lib/core/services/dictionary_service.dart | 196 ++++++++------- lib/core/services/navigator_service.dart | 10 +- lib/core/utils/logger.dart | 2 +- lib/routes/route_names.dart | 13 +- lib/routes/router.dart | 16 +- .../dictionaries/category/category_edit.dart | 42 +--- .../category/category_select_view.dart | 133 +++++----- .../dictionaries/category/category_view.dart | 127 +++++----- .../contragents/contragents_edit.dart | 170 +++++++++++++ .../contragents/contragents_view.dart | 141 +++++++++++ lib/views/dictionaries/goods/goods_edit.dart | 43 ++-- lib/views/dictionaries/goods/goods_view.dart | 125 +++++----- lib/views/login/login_view.dart | 137 ++++------- lib/views/main/main_view.dart | 7 +- .../printer_bluetooth/printer_select.dart | 3 - .../printer_bluetooth/printer_view.dart | 1 - lib/views/settings/setting_view.dart | 1 - lib/views/start_up/start_up_view.dart | 4 - lib/views/work/tabs/buy_view.dart | 3 - .../tabs/component/contagent_select_bar.dart | 6 +- .../work/tabs/component/custom_field.dart | 4 +- .../tabs/component/dialog_edit_product.dart | 4 +- .../tabs/component/product_list_item.dart | 3 - .../work/tabs/component/transaction_item.dart | 96 ++++---- lib/views/work/tabs/journal_view.dart | 2 - lib/views/work/tabs/sell_view.dart | 15 +- .../add_by_barcode/add_by_barcode_view.dart | 2 - .../views/add_product/add_product_view.dart | 56 +++-- .../component/add_category_list_item.dart | 7 +- .../component/add_product_list_item.dart | 1 - .../companent/contragent_list_item.dart | 3 - .../contragent/select_contragent_view.dart | 3 - .../views/payment/component/combine_dock.dart | 1 - .../work/views/payment/payment_view.dart | 2 - .../work/views/receipt/receipt_view.dart | 3 - lib/views/work/work_view.dart | 2 - lib/widgets/bar/products_app_bar.dart | 15 +- lib/widgets/bar/products_header_bar.dart | 3 - lib/widgets/buttons/aman_icon_button.dart | 2 - lib/widgets/buttons/busy_button.dart | 19 +- lib/widgets/dialog/dialog_manager.dart | 8 +- lib/widgets/dialog/modal_select_dialog.dart | 8 +- lib/widgets/drawer/app_drawer.dart | 227 +++++++++++------- lib/widgets/fields/dropdown_field.dart | 2 - lib/widgets/fields/input_checkbox.dart | 67 ++++++ lib/widgets/fields/input_field.dart | 40 +-- lib/widgets/fields/input_field_rounded.dart | 58 ++--- lib/widgets/fields/line_checkbox.dart | 1 - lib/widgets/fields/note_text.dart | 1 - .../tools/app_barcode_scanner_widget.dart | 2 - lib/widgets/ui/product_title_widget.dart | 2 - pubspec.lock | 51 ++-- pubspec.yaml | 15 +- 86 files changed, 1466 insertions(+), 949 deletions(-) create mode 100644 assets/images/svg/ostatki.svg create mode 100644 lib/core/models/dictionary/contragent/contragent_response_entity.dart create mode 100644 lib/core/models/dictionary/contragent/contragent_response_entity.g.dart create mode 100644 lib/core/models/dictionary/response/dict_response_entity.dart create mode 100644 lib/core/models/dictionary/response/dict_response_entity.g.dart delete mode 100644 lib/core/models/response.dart create mode 100644 lib/views/dictionaries/contragents/contragents_edit.dart create mode 100644 lib/views/dictionaries/contragents/contragents_view.dart create mode 100644 lib/widgets/fields/input_checkbox.dart diff --git a/README.md b/README.md index 615dd76..d0078ed 100644 --- a/README.md +++ b/README.md @@ -1,19 +1,16 @@ # satu - Aman Satu App ## Getting Started -This project is a starting point for a Flutter application. +# build_runner +flutter pub run build_runner build --delete-conflicting-outputs +flutter pub run build_runner watch --delete-conflicting-outputs -A few resources to get you started if this is your first Flutter project: - -- [Lab: Write your first Flutter app](https://flutter.dev/docs/get-started/codelab) -- [Cookbook: Useful Flutter samples](https://flutter.dev/docs/cookbook) - -For help getting started with Flutter, view our -[online documentation](https://flutter.dev/docs), which offers tutorials, -samples, guidance on mobile development, and a full API reference. +# build android apk +flutter build --release apk --flavor production +# build android appbundle +flutter build --release appbundle --flavor production ## Сборка релизного пакет flutter clean && flutter build appbundle --release \ No newline at end of file diff --git a/assets/images/svg/ostatki.svg b/assets/images/svg/ostatki.svg new file mode 100644 index 0000000..ad38c10 --- /dev/null +++ b/assets/images/svg/ostatki.svg @@ -0,0 +1,12 @@ + + + + + + + + + diff --git a/lib/core/base/base_service.dart b/lib/core/base/base_service.dart index 0b4dc62..523d464 100644 --- a/lib/core/base/base_service.dart +++ b/lib/core/base/base_service.dart @@ -3,13 +3,13 @@ import 'package:logger/logger.dart'; import '../utils/logger.dart'; class BaseService { - Logger log = getLogger( - 'BaseService', - ); BaseService({String? title}) { this.log = getLogger( title ?? this.runtimeType.toString(), ); } + Logger log = getLogger( + 'BaseService', + ); } \ No newline at end of file diff --git a/lib/core/models/dialog_models.dart b/lib/core/models/dialog_models.dart index 4e74c56..d4368fa 100644 --- a/lib/core/models/dialog_models.dart +++ b/lib/core/models/dialog_models.dart @@ -1,4 +1,3 @@ -import 'package:flutter/foundation.dart'; class DialogRequest { DialogRequest( diff --git a/lib/core/models/dictionary/category_response.dart b/lib/core/models/dictionary/category_response.dart index b78a01f..1b16082 100644 --- a/lib/core/models/dictionary/category_response.dart +++ b/lib/core/models/dictionary/category_response.dart @@ -9,11 +9,10 @@ class CategoryResponse { String name = ''; String? updatedAt; - static CategoryResponse? fromMap(dynamic map) { - if (map == null) return null; + static CategoryResponse fromMap(dynamic map) { final CategoryResponse categoryResponseBean = CategoryResponse(); categoryResponseBean.id = map['id'] as int; - categoryResponseBean.parentId = map['parent_id'] as int; + categoryResponseBean.parentId = map['parent_id'] as int?; categoryResponseBean.name = map['name'] as String; categoryResponseBean.updatedAt = map['updated_at'] as String; return categoryResponseBean; diff --git a/lib/core/models/dictionary/contragent/contragent_response_entity.dart b/lib/core/models/dictionary/contragent/contragent_response_entity.dart new file mode 100644 index 0000000..4e54b73 --- /dev/null +++ b/lib/core/models/dictionary/contragent/contragent_response_entity.dart @@ -0,0 +1,29 @@ +import 'package:json_annotation/json_annotation.dart'; +import 'dart:convert'; + +part 'contragent_response_entity.g.dart'; + +@JsonSerializable() +class ContragentResponseEntity { + factory ContragentResponseEntity.fromJson(Map json) => + _$ContragentResponseEntityFromJson(json); + + ContragentResponseEntity(); + + int? id; + String? biniin; + @JsonKey(name: 'ref_app_company_type_id') + late int refAppCompanyTypeId; + String? name; + String? phone; + String? email; + int? nds; + int? resident; + + Map toJson() => _$ContragentResponseEntityToJson(this); + + @override + String toString() { + return jsonEncode(this); + } +} diff --git a/lib/core/models/dictionary/contragent/contragent_response_entity.g.dart b/lib/core/models/dictionary/contragent/contragent_response_entity.g.dart new file mode 100644 index 0000000..035d075 --- /dev/null +++ b/lib/core/models/dictionary/contragent/contragent_response_entity.g.dart @@ -0,0 +1,32 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'contragent_response_entity.dart'; + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +ContragentResponseEntity _$ContragentResponseEntityFromJson( + Map json) => + ContragentResponseEntity() + ..id = json['id'] as int? + ..biniin = json['biniin'] as String? + ..refAppCompanyTypeId = json['ref_app_company_type_id'] as int + ..name = json['name'] as String? + ..phone = json['phone'] as String? + ..email = json['email'] as String? + ..nds = json['nds'] as int? + ..resident = json['resident'] as int?; + +Map _$ContragentResponseEntityToJson( + ContragentResponseEntity instance) => + { + 'id': instance.id, + 'biniin': instance.biniin, + 'ref_app_company_type_id': instance.refAppCompanyTypeId, + 'name': instance.name, + 'phone': instance.phone, + 'email': instance.email, + 'nds': instance.nds, + 'resident': instance.resident, + }; diff --git a/lib/core/models/dictionary/good_response.dart b/lib/core/models/dictionary/good_response.dart index c5bc1ea..9dafb67 100644 --- a/lib/core/models/dictionary/good_response.dart +++ b/lib/core/models/dictionary/good_response.dart @@ -22,19 +22,22 @@ class GoodResponse { double? basePrice; int? divisible; String? updatedAt; + String? categoryName; + static GoodResponse fromMap(dynamic map) { final GoodResponse goodResponseBean = GoodResponse(); goodResponseBean.id = map['id'] as int; - goodResponseBean.categoryId = map['category_id'] as int; + goodResponseBean.categoryId = map['eacc_good_category_id'] as int?; goodResponseBean.name = map['name'] as String; - goodResponseBean.ean = map['ean'] as String; + goodResponseBean.ean = map['ean'] as String?; goodResponseBean.articul = map['articul'] as int; goodResponseBean.price = (cast(map['price']) ?? 0).toDouble() ; goodResponseBean.optPrice = (cast(map['opt_price']) ?? 0).toDouble(); goodResponseBean.basePrice = (cast(map['base_price']) ?? 0).toDouble(); - goodResponseBean.divisible = map['divisible'] as int; + goodResponseBean.divisible = map['divisible'] as int?; goodResponseBean.updatedAt = map['updated_at'] as String; + goodResponseBean.categoryName = map['category_name'] as String?; return goodResponseBean; } diff --git a/lib/core/models/dictionary/response/dict_response_entity.dart b/lib/core/models/dictionary/response/dict_response_entity.dart new file mode 100644 index 0000000..7e0a9e8 --- /dev/null +++ b/lib/core/models/dictionary/response/dict_response_entity.dart @@ -0,0 +1,62 @@ +import 'package:json_annotation/json_annotation.dart'; +import 'dart:convert'; + +part 'dict_response_entity.g.dart'; + +@JsonSerializable() +class DictResponseEntity { + + factory DictResponseEntity.fromJson(Map json) => _$DictResponseEntityFromJson(json); + + DictResponseEntity(); + + late DictResponseHeaders headers; + late DictResponseOriginal original; + String? exception; + + Map toJson() => _$DictResponseEntityToJson(this); + + @override + String toString() { + return jsonEncode(this); + } +} + +@JsonSerializable() +class DictResponseHeaders { + + + + DictResponseHeaders(); + + factory DictResponseHeaders.fromJson(Map json) => _$DictResponseHeadersFromJson(json); + + Map toJson() => _$DictResponseHeadersToJson(this); + + @override + String toString() { + return jsonEncode(this); + } +} + +@JsonSerializable() +class DictResponseOriginal { + + factory DictResponseOriginal.fromJson(Map json) => _$DictResponseOriginalFromJson(json); + + DictResponseOriginal(); + + int? overall; + int? page; + int? perpage; + List? data; + Map>? errors; + String? message; + + Map toJson() => _$DictResponseOriginalToJson(this); + + @override + String toString() { + return jsonEncode(this); + } +} diff --git a/lib/core/models/dictionary/response/dict_response_entity.g.dart b/lib/core/models/dictionary/response/dict_response_entity.g.dart new file mode 100644 index 0000000..c5923d8 --- /dev/null +++ b/lib/core/models/dictionary/response/dict_response_entity.g.dart @@ -0,0 +1,53 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'dict_response_entity.dart'; + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +DictResponseEntity _$DictResponseEntityFromJson(Map json) => + DictResponseEntity() + ..headers = + DictResponseHeaders.fromJson(json['headers'] as Map) + ..original = DictResponseOriginal.fromJson( + json['original'] as Map) + ..exception = json['exception'] as String?; + +Map _$DictResponseEntityToJson(DictResponseEntity instance) => + { + 'headers': instance.headers, + 'original': instance.original, + 'exception': instance.exception, + }; + +DictResponseHeaders _$DictResponseHeadersFromJson(Map json) => + DictResponseHeaders(); + +Map _$DictResponseHeadersToJson( + DictResponseHeaders instance) => + {}; + +DictResponseOriginal _$DictResponseOriginalFromJson( + Map json) => + DictResponseOriginal() + ..overall = json['overall'] as int? + ..page = json['page'] as int? + ..perpage = json['perpage'] as int? + ..data = json['data'] as List? + ..errors = (json['errors'] as Map?)?.map( + (k, e) => + MapEntry(k, (e as List).map((e) => e as String).toList()), + ) + ..message = json['message'] as String?; + +Map _$DictResponseOriginalToJson( + DictResponseOriginal instance) => + { + 'overall': instance.overall, + 'page': instance.page, + 'perpage': instance.perpage, + 'data': instance.data, + 'errors': instance.errors, + 'message': instance.message, + }; diff --git a/lib/core/models/flow/dao/transaction_dao.dart b/lib/core/models/flow/dao/transaction_dao.dart index 8888d20..1dd815d 100644 --- a/lib/core/models/flow/dao/transaction_dao.dart +++ b/lib/core/models/flow/dao/transaction_dao.dart @@ -1,4 +1,3 @@ -import 'package:satu/core/utils/utils_parse.dart'; class TransactionDao { TransactionDao(); diff --git a/lib/core/models/flow/sell_return/sell_return_request.dart b/lib/core/models/flow/sell_return/sell_return_request.dart index c99a3e3..c12e312 100644 --- a/lib/core/models/flow/sell_return/sell_return_request.dart +++ b/lib/core/models/flow/sell_return/sell_return_request.dart @@ -4,13 +4,13 @@ part 'sell_return_request.g.dart'; @JsonSerializable() class SellReturnRequest { - int journal_id; - String invoice_id; + factory SellReturnRequest.fromJson(Map json) => + _$SellReturnRequestFromJson(json); SellReturnRequest({required this.journal_id, required this.invoice_id}); - factory SellReturnRequest.fromJson(Map json) => _$SellReturnRequestFromJson(json); + int journal_id; + String invoice_id; Map toJson() => _$SellReturnRequestToJson(this); } - diff --git a/lib/core/models/flow/sell_return/sell_return_request.g.dart b/lib/core/models/flow/sell_return/sell_return_request.g.dart index 84939ce..5aed66c 100644 --- a/lib/core/models/flow/sell_return/sell_return_request.g.dart +++ b/lib/core/models/flow/sell_return/sell_return_request.g.dart @@ -6,12 +6,11 @@ part of 'sell_return_request.dart'; // JsonSerializableGenerator // ************************************************************************** -SellReturnRequest _$SellReturnRequestFromJson(Map json) { - return SellReturnRequest( - journal_id: json['journal_id'] as int, - invoice_id: json['invoice_id'] as String, - ); -} +SellReturnRequest _$SellReturnRequestFromJson(Map json) => + SellReturnRequest( + journal_id: json['journal_id'] as int, + invoice_id: json['invoice_id'] as String, + ); Map _$SellReturnRequestToJson(SellReturnRequest instance) => { diff --git a/lib/core/models/response.dart b/lib/core/models/response.dart deleted file mode 100644 index 1ed9660..0000000 --- a/lib/core/models/response.dart +++ /dev/null @@ -1,34 +0,0 @@ -import 'package:satu/core/utils/utils_parse.dart'; - -/// list : [] -/// message : "" -/// operation : true - -class Response { - List? list; - String? message; - bool? operation; - - Response(); - - factory Response.fromMapList(dynamic map, Function(dynamic)? parser) { - - final List list = []; - if (map['list'] != null) { - (map['list'] as List).forEach((dynamic element) { - if(parser == null) { - list.add(element); - } else { - list.add(parser(element)); - } - }); - } - final Response responseBean = Response(); - responseBean.list = list; - responseBean.message = cast(map['message']); - responseBean.operation = map['operation'] as bool; - return responseBean; - } - - -} diff --git a/lib/core/models/settings/printer_setting.dart b/lib/core/models/settings/printer_setting.dart index 1590594..32432b4 100644 --- a/lib/core/models/settings/printer_setting.dart +++ b/lib/core/models/settings/printer_setting.dart @@ -12,6 +12,14 @@ class PrinterConst { class PrinterSetting { + factory PrinterSetting.fromMap(dynamic map) { + return PrinterSetting( + device: map['device']!=null ? PrinterDevice.fromMap(map['device']) : null, + encoding: cast(map['encoding']), + paperSize: cast(map['paperSize']), + ); + } + PrinterSetting({ this.device, this.encoding = PrinterConst.encodingCP866, @@ -30,37 +38,9 @@ class PrinterSetting { }; } - factory PrinterSetting.fromMap(dynamic map) { - return PrinterSetting( - device: map['device']!=null ? PrinterDevice.fromMap(map['device']) : null, - encoding: cast(map['encoding']), - paperSize: cast(map['paperSize']), - ); - } - } class PrinterDevice { - String? name; - String? address; - int? type = 0; - bool? connected = false; - - PrinterDevice({ - this.name, - this.address, - this.type, - this.connected, - }); - - dynamic toMap() { - return { - 'name': name, - 'address': address, - 'type': type, - 'connected': connected, - }; - } factory PrinterDevice.fromMap(dynamic map) { return PrinterDevice( @@ -70,4 +50,24 @@ class PrinterDevice { connected: cast(map['connected']), ); } + + PrinterDevice({ + this.name, + this.address, + this.type, + this.connected, + }); + String? name; + String? address; + int? type = 0; + bool? connected = false; + + dynamic toMap() { + return { + 'name': name, + 'address': address, + 'type': type, + 'connected': connected, + }; + } } \ No newline at end of file diff --git a/lib/core/models/ui_dao/popup_item_dao.dart b/lib/core/models/ui_dao/popup_item_dao.dart index 9b355e0..f063dd3 100644 --- a/lib/core/models/ui_dao/popup_item_dao.dart +++ b/lib/core/models/ui_dao/popup_item_dao.dart @@ -1,4 +1,3 @@ -import 'package:satu/core/utils/utils_parse.dart'; class PopupItemDao { PopupItemDao({required this.code, required this.name}); diff --git a/lib/core/redux/actions/journal_actions.dart b/lib/core/redux/actions/journal_actions.dart index ecf31a6..380829c 100644 --- a/lib/core/redux/actions/journal_actions.dart +++ b/lib/core/redux/actions/journal_actions.dart @@ -5,20 +5,13 @@ import 'package:logger/logger.dart'; import 'package:meta/meta.dart'; import 'package:redux/redux.dart'; import 'package:redux_thunk/redux_thunk.dart'; -import 'package:satu/core/entity/category_entity.dart'; -import 'package:satu/core/entity/goods_entity.dart'; import 'package:satu/core/entity/transaction_entity.dart'; -import 'package:satu/core/entity/transaction_rec_entity.dart'; import 'package:satu/core/models/entity_data/transaction_data.dart'; -import 'package:satu/core/models/flow/dao/product_dao.dart'; import 'package:satu/core/models/flow/dao/transaction_dao.dart'; -import 'package:satu/core/models/flow/transaction_state.dart'; import 'package:satu/core/redux/state/journal_state.dart'; -import 'package:satu/core/redux/state/sell_state.dart'; import 'package:satu/core/services/db_service.dart'; import 'package:satu/core/utils/locator.dart'; import 'package:satu/core/utils/logger.dart'; -import 'package:uuid/uuid.dart'; import '../store.dart'; @@ -44,7 +37,6 @@ Future loadJournalData(Store store) async { try { log.i('loadJournalData'); final int? appCompanyId = store.state.userState!.auth!.companyId; - final int tabIndex = store.state.journalState?.tabIndex ?? 0; final List> set = await _dbService.queryRowsWithWhere( transactionTableName, '$transactionColumnAppCompanyId = ?' @@ -75,7 +67,7 @@ Future loadJournalData(Store store) async { dao.contragentName = data.contragentName; dao.number = data.sellResponse?.journalId.toString() ?? ''; dao.total = data.total; - if(transaction.type == transactionTypeReturnSell) { + if (transaction.type == transactionTypeReturnSell) { dao.received = false; } diff --git a/lib/core/redux/actions/nav_actions.dart b/lib/core/redux/actions/nav_actions.dart index 4827c24..19212fd 100644 --- a/lib/core/redux/actions/nav_actions.dart +++ b/lib/core/redux/actions/nav_actions.dart @@ -8,8 +8,8 @@ import '../store.dart'; @immutable class SetNavStateAction { - final NavState navState; SetNavStateAction(this.navState); + final NavState navState; } ThunkAction navigateDrawer(Type viewClass) { diff --git a/lib/core/redux/actions/setting_actions.dart b/lib/core/redux/actions/setting_actions.dart index a216304..c07d55c 100644 --- a/lib/core/redux/actions/setting_actions.dart +++ b/lib/core/redux/actions/setting_actions.dart @@ -1,26 +1,11 @@ -import 'dart:convert'; -import 'package:intl/intl.dart'; import 'package:logger/logger.dart'; import 'package:meta/meta.dart'; import 'package:redux/redux.dart'; import 'package:redux_thunk/redux_thunk.dart'; -import 'package:satu/core/entity/category_entity.dart'; -import 'package:satu/core/entity/goods_entity.dart'; -import 'package:satu/core/entity/transaction_entity.dart'; -import 'package:satu/core/entity/transaction_rec_entity.dart'; -import 'package:satu/core/models/entity_data/transaction_data.dart'; -import 'package:satu/core/models/flow/dao/product_dao.dart'; -import 'package:satu/core/models/flow/dao/transaction_dao.dart'; -import 'package:satu/core/models/flow/transaction_state.dart'; import 'package:satu/core/models/settings/printer_setting.dart'; -import 'package:satu/core/redux/state/journal_state.dart'; -import 'package:satu/core/redux/state/sell_state.dart'; import 'package:satu/core/redux/state/setting_state.dart'; -import 'package:satu/core/services/db_service.dart'; -import 'package:satu/core/utils/locator.dart'; import 'package:satu/core/utils/logger.dart'; -import 'package:uuid/uuid.dart'; import '../store.dart'; diff --git a/lib/core/redux/actions/user_actions.dart b/lib/core/redux/actions/user_actions.dart index 274202d..1533724 100644 --- a/lib/core/redux/actions/user_actions.dart +++ b/lib/core/redux/actions/user_actions.dart @@ -13,9 +13,9 @@ import '../store.dart'; @immutable class SetUserStateAction { - final UserState userState; SetUserStateAction(this.userState); + final UserState userState; } final ApiService _api = locator(); diff --git a/lib/core/redux/reducers/journal_reducer.dart b/lib/core/redux/reducers/journal_reducer.dart index fcca4cb..3c7f40d 100644 --- a/lib/core/redux/reducers/journal_reducer.dart +++ b/lib/core/redux/reducers/journal_reducer.dart @@ -1,9 +1,5 @@ import 'package:satu/core/redux/actions/journal_actions.dart'; -import 'package:satu/core/redux/actions/sell_actions.dart'; -import 'package:satu/core/redux/actions/user_actions.dart'; import 'package:satu/core/redux/state/journal_state.dart'; -import 'package:satu/core/redux/state/sell_state.dart'; -import 'package:satu/core/redux/state/user_state.dart'; JournalState journalReducer( JournalState prevState, SetJournalStateAction action) { diff --git a/lib/core/redux/reducers/nav_reducer.dart b/lib/core/redux/reducers/nav_reducer.dart index c762d03..aee9c3f 100644 --- a/lib/core/redux/reducers/nav_reducer.dart +++ b/lib/core/redux/reducers/nav_reducer.dart @@ -1,7 +1,5 @@ import 'package:satu/core/redux/actions/nav_actions.dart'; -import 'package:satu/core/redux/actions/user_actions.dart'; import 'package:satu/core/redux/state/nav_state.dart'; -import 'package:satu/core/redux/state/user_state.dart'; NavState navReducer(NavState prevState, SetNavStateAction action) { final NavState payload = action.navState; diff --git a/lib/core/redux/reducers/sell_reducer.dart b/lib/core/redux/reducers/sell_reducer.dart index e63050c..c9dba15 100644 --- a/lib/core/redux/reducers/sell_reducer.dart +++ b/lib/core/redux/reducers/sell_reducer.dart @@ -1,7 +1,5 @@ import 'package:satu/core/redux/actions/sell_actions.dart'; -import 'package:satu/core/redux/actions/user_actions.dart'; import 'package:satu/core/redux/state/sell_state.dart'; -import 'package:satu/core/redux/state/user_state.dart'; SellState sellReducer(SellState prevState, SetSellStateAction action) { final SellState payload = action.sellState; diff --git a/lib/core/redux/reducers/setting_reducer.dart b/lib/core/redux/reducers/setting_reducer.dart index 64df633..cabd559 100644 --- a/lib/core/redux/reducers/setting_reducer.dart +++ b/lib/core/redux/reducers/setting_reducer.dart @@ -1,11 +1,5 @@ -import 'package:satu/core/redux/actions/journal_actions.dart'; -import 'package:satu/core/redux/actions/sell_actions.dart'; import 'package:satu/core/redux/actions/setting_actions.dart'; -import 'package:satu/core/redux/actions/user_actions.dart'; -import 'package:satu/core/redux/state/journal_state.dart'; -import 'package:satu/core/redux/state/sell_state.dart'; import 'package:satu/core/redux/state/setting_state.dart'; -import 'package:satu/core/redux/state/user_state.dart'; SettingState settingReducer( SettingState prevState, SetSettingStateAction action) { diff --git a/lib/core/redux/state/nav_state.dart b/lib/core/redux/state/nav_state.dart index 9b07437..6a1e282 100644 --- a/lib/core/redux/state/nav_state.dart +++ b/lib/core/redux/state/nav_state.dart @@ -3,8 +3,6 @@ import 'package:satu/views/work/work_view.dart'; @immutable class NavState { - final Type? drawerViewClass; - final int? selectedTabIndex; NavState({this.drawerViewClass, this.selectedTabIndex}); @@ -12,6 +10,8 @@ class NavState { drawerViewClass: WorkView, selectedTabIndex: 0, ); + final Type? drawerViewClass; + final int? selectedTabIndex; NavState copyWith({ required int? selectedTabIndex, diff --git a/lib/core/redux/state/sell_state.dart b/lib/core/redux/state/sell_state.dart index ec74111..d5ebf93 100644 --- a/lib/core/redux/state/sell_state.dart +++ b/lib/core/redux/state/sell_state.dart @@ -1,23 +1,24 @@ import 'package:meta/meta.dart'; -import 'package:satu/core/models/auth/auth_response.dart'; import 'package:satu/core/models/flow/dao/product_dao.dart'; import 'package:satu/core/models/flow/transaction_state.dart'; @immutable class SellState { - final List? items; - final TransactionState? transactionState; - - SellState({this.items, this.transactionState}); - factory SellState.initial() => SellState( items: [], transactionState: TransactionState(), ); - SellState copyWith({required List? items, required TransactionState? transactionState}) { - return SellState(items: items ?? this.items, transactionState: transactionState ?? this.transactionState); + SellState({this.items, this.transactionState}); + + final List? items; + final TransactionState? transactionState; + + SellState copyWith( + {required List? items, + required TransactionState? transactionState}) { + return SellState( + items: items ?? this.items, + transactionState: transactionState ?? this.transactionState); } } - - diff --git a/lib/core/redux/state/setting_state.dart b/lib/core/redux/state/setting_state.dart index d918017..ca33139 100644 --- a/lib/core/redux/state/setting_state.dart +++ b/lib/core/redux/state/setting_state.dart @@ -1,9 +1,17 @@ import 'package:meta/meta.dart'; -import 'package:satu/core/models/flow/dao/transaction_dao.dart'; import 'package:satu/core/models/settings/printer_setting.dart'; @immutable class SettingState { + + factory SettingState.fromMap(dynamic map) { + if (map == null) return SettingState.initial(null); + return SettingState( + printer: map['printer'] != null + ? PrinterSetting.fromMap(map['printer']) + : null, + ); + } const SettingState({this.printer}); factory SettingState.initial(SettingState? settingState) => @@ -20,13 +28,4 @@ class SettingState { 'printer': printer !=null ? printer!.toMap() : null, }; } - - factory SettingState.fromMap(dynamic map) { - if (map == null) return SettingState.initial(null); - return SettingState( - printer: map['printer'] != null - ? PrinterSetting.fromMap(map['printer']) - : null, - ); - } } diff --git a/lib/core/redux/state/user_state.dart b/lib/core/redux/state/user_state.dart index 58662a5..b440fcb 100644 --- a/lib/core/redux/state/user_state.dart +++ b/lib/core/redux/state/user_state.dart @@ -5,9 +5,12 @@ import 'package:satu/core/models/auth/auth_response.dart'; @immutable class UserState { - final bool? isError; - final bool? isLoading; - final AuthResponse? auth; + + factory UserState.initial(UserState? payload) => UserState( + isLoading: false, + isError: false, + auth: payload?.auth ?? (AuthResponse()..operation=false), + ); UserState( @@ -15,12 +18,9 @@ class UserState { this.isLoading, this.auth, }); - - factory UserState.initial(UserState? payload) => UserState( - isLoading: false, - isError: false, - auth: payload?.auth ?? (AuthResponse()..operation=false), - ); + final bool? isError; + final bool? isLoading; + final AuthResponse? auth; UserState copyWith({ required bool? isError, diff --git a/lib/core/redux/store.dart b/lib/core/redux/store.dart index 0c653aa..4229660 100644 --- a/lib/core/redux/store.dart +++ b/lib/core/redux/store.dart @@ -120,7 +120,8 @@ class Redux { final navStateInitial = NavState.initial(); final sellStateInitial = SellState.initial(); final journalStateInitial = JournalState.initial(); - final settingStateInitial = SettingState.initial(initialState?.settingState); + final settingStateInitial = + SettingState.initial(initialState?.settingState); _store = Store( appReducer, diff --git a/lib/core/services/api_service.dart b/lib/core/services/api_service.dart index 19ea1a6..d8ff2b0 100644 --- a/lib/core/services/api_service.dart +++ b/lib/core/services/api_service.dart @@ -4,18 +4,18 @@ import 'dart:io'; import 'package:satu/core/base/base_service.dart'; import 'package:http/http.dart' as http; import 'package:satu/core/models/auth/auth_response.dart'; +import 'package:satu/core/models/dictionary/response/dict_response_entity.dart'; import 'package:satu/core/models/flow/analytics/analytics_bean.dart'; import 'package:satu/core/models/flow/sell_request.dart'; import 'package:satu/core/models/flow/sell_response.dart'; import 'package:satu/core/models/flow/sell_return/sell_return_request.dart'; -import 'package:satu/core/models/response.dart'; /// The service responsible for networking requests class ApiService extends BaseService { static const host = 'satu.aman.com.kz'; static const endpoint = '/api/v1'; - http.Client client = http.Client(); + //TOKEN String? token; @@ -38,15 +38,18 @@ class ApiService extends BaseService { {Map? requestBody, Map? header}) async { final Map headers = { HttpHeaders.contentTypeHeader: 'application/json', - HttpHeaders.cacheControlHeader: 'no-cache' + HttpHeaders.cacheControlHeader: 'no-cache', }; if (header != null && header.isNotEmpty) { headers.addAll(header); } final String url = '$endpoint$point'; - if (requestBody != null) { - log.i(jsonEncode(requestBody)); - } + // if (requestBody != null) { + // log.i(host); + // log.i(url); + // log.i(headers); + // log.i(jsonEncode(requestBody)); + // } final response = await http.post(Uri.https(host, url), body: jsonEncode(requestBody), headers: headers); @@ -121,36 +124,55 @@ class ApiService extends BaseService { return result; } - Future dictionaries(String target) async { - Response result; + Future dictionaries(String target, + {Map? requestBody}) async { + DictResponseEntity result; try { final Map headers = { HttpHeaders.authorizationHeader: 'Bearer $token' }; - final String response = await _post(target, header: headers); - result = Response.fromMapList(json.decode(response), null); + + final String response = + await _post(target, header: headers, requestBody: requestBody); + result = DictResponseEntity.fromJson(json.decode(response)); } catch (e, stack) { log.e('dictionaries', e, stack); - result = Response() - ..operation = false - ..list = []; + result = DictResponseEntity()..exception = e.toString(); } return result; } + Future dictionarySave( + String target, Map? body) async { + DictResponseEntity response; + try { + final Map headers = { + HttpHeaders.authorizationHeader: 'Bearer $token' + }; + final String responseBody = + await _post(target, header: headers, requestBody: body); + response = DictResponseEntity.fromJson(json.decode(responseBody)); + } catch (e, stack) { + log.e('dictionarySave', e, stack); + response = DictResponseEntity()..exception = e.toString(); + } + return response; + } + Future sell(SellRequest request) async { SellResponse response; try { final Map headers = { HttpHeaders.authorizationHeader: 'Bearer $token' }; - final String responseBody = await _post('/sell', header: headers, requestBody: request.toJson()); + final String responseBody = + await _post('/sell', header: headers, requestBody: request.toJson()); response = SellResponse.fromMap(json.decode(responseBody)); } catch (e, stack) { log.e('dictionaries', e, stack); response = SellResponse() ..operation = false - ..message = e.toString(); + ..message = e.toString(); } return response; } @@ -161,7 +183,8 @@ class ApiService extends BaseService { final Map headers = { HttpHeaders.authorizationHeader: 'Bearer $token' }; - final String responseBody = await _post('/sell_return', header: headers, requestBody: request.toJson()); + final String responseBody = await _post('/sell_return', + header: headers, requestBody: request.toJson()); response = SellResponse.fromMap(json.decode(responseBody)); } catch (e, stack) { log.e('sellReturn', e, stack); @@ -179,7 +202,6 @@ class ApiService extends BaseService { HttpHeaders.authorizationHeader: 'Bearer $token' }; final String responseBody = await _get('/get_analytics', header: headers); - log.i(responseBody); response = AnalyticsBean.fromMap(json.decode(responseBody)); } catch (e, stack) { log.e('getAnalytics', e, stack); diff --git a/lib/core/services/data_service.dart b/lib/core/services/data_service.dart index 373c46a..0079628 100644 --- a/lib/core/services/data_service.dart +++ b/lib/core/services/data_service.dart @@ -1,6 +1,5 @@ import 'dart:convert'; -import 'package:flutter/material.dart'; import 'package:satu/core/base/base_service.dart'; import 'package:satu/core/entity/transaction_entity.dart'; import 'package:satu/core/models/entity_data/transaction_data.dart'; @@ -160,7 +159,6 @@ class DataService extends BaseService { transaction.data = jsonEncode(data.toMap()); log.i(jsonEncode(data.toMap())); return await _db.insert(transactionTableName, transaction.toMap()); - ; } ItemBean _productToItemBean(ProductDao product) { diff --git a/lib/core/services/db_service.dart b/lib/core/services/db_service.dart index 0c6c4f3..77be000 100644 --- a/lib/core/services/db_service.dart +++ b/lib/core/services/db_service.dart @@ -10,11 +10,11 @@ import 'package:path/path.dart'; import 'package:path_provider/path_provider.dart'; class DbService extends BaseService { - static const _databaseName = 'AmanSatuDb.db'; - static const _databaseVersion = 2; // make this a singleton class DbService._privateConstructor(); + static const _databaseName = 'AmanSatuDb.db'; + static const _databaseVersion = 2; static final DbService instance = DbService._privateConstructor(); diff --git a/lib/core/services/dialog_service.dart b/lib/core/services/dialog_service.dart index f6b8913..64f1499 100644 --- a/lib/core/services/dialog_service.dart +++ b/lib/core/services/dialog_service.dart @@ -21,7 +21,8 @@ class DialogService { _showDialogInputListener = showDialogInputListener; } - /// Calls the dialog listener and returns a Future that will wait for dialogComplete. + /// Calls the dialog listener + /// and returns a Future that will wait for dialogComplete. Future showDialog({ String title = 'SATU', String? description, diff --git a/lib/core/services/dictionary_service.dart b/lib/core/services/dictionary_service.dart index 215fcca..af2475d 100644 --- a/lib/core/services/dictionary_service.dart +++ b/lib/core/services/dictionary_service.dart @@ -2,8 +2,9 @@ import 'package:satu/core/base/base_service.dart'; import 'package:satu/core/entity/category_entity.dart'; import 'package:satu/core/entity/goods_entity.dart'; import 'package:satu/core/models/dictionary/category_response.dart'; +import 'package:satu/core/models/dictionary/contragent/contragent_response_entity.dart'; import 'package:satu/core/models/dictionary/good_response.dart'; -import 'package:satu/core/models/response.dart'; +import 'package:satu/core/models/dictionary/response/dict_response_entity.dart'; import 'package:satu/core/redux/store.dart'; import 'package:satu/core/utils/locator.dart'; @@ -15,32 +16,10 @@ class DictionaryService extends BaseService { final DbService _db = locator(); Future refreshFull() async { - _db.deleteAll(categoryTableName); - await refreshCategory(); - _db.deleteAll(goodTableName); - await refreshGood(); + } - Future refreshCategory() async { - try { - final int? appCompanyId = Redux.store!.state.userState!.auth!.companyId; - final Response categories = await _api.dictionaries('/categories'); - if (categories.operation! && categories.list!.isNotEmpty) { - for (dynamic map in categories.list!) { - CategoryResponse cat = CategoryResponse.fromMap(map)!; - Category entity = new Category() - ..id = cat.id - ..name = cat.name - ..updatedAt = cat.updatedAt - ..parentId = cat.parentId - ..appCompanyId = appCompanyId; - _db.insert(categoryTableName, entity.toMap()); - } - } - } catch (e, stack) { - log.e('categories', e, stack); - } - } + Future> getCategoryByParentId(int parentId) async { final List list = []; @@ -77,23 +56,7 @@ class DictionaryService extends BaseService { return result; } - Future> getCategoriesAll() async { - final List list = []; - try { - final int? appCompanyId = Redux.store?.state.userState?.auth?.companyId; - final List> elements = await _db.queryRowsWithWhere( - categoryTableName, - '$categoryColumnAppCompanyId = ? ' - ' order by $categoryColumnParentIn asc, $categoryColumnId asc ', - [appCompanyId]); - for (final Map element in elements) { - list.add(Category.fromMap(element)); - } - } catch (e, stack) { - log.e('getCategoriesAll', e, stack); - } - return list; - } + Future> getGoodsByCategoryId(int categoryId) async { final List list = []; @@ -134,55 +97,126 @@ class DictionaryService extends BaseService { return list; } - Future> getGoodsByEan(String code) async { - final List list = []; - try { - final int? appCompanyId = Redux.store?.state.userState?.auth?.companyId; - final String where = - '( $GoodColumnAppCompanyId = ? and $GoodColumnEan like ? ) '; - final List args = [appCompanyId, '%$code%']; - final List> elements = - await _db.queryRowsWithWhere(goodTableName, where, args); - for (final Map element in elements) { - list.add(Good.fromMap(element)); - } - } catch (e, stack) { - log.e('getGoodsByEan', e, stack); - } - return list; - } - - bool _isNumericInt(String str) { + bool _isNumericInt(String? str) { if (str == null) { return false; } return int.tryParse(str) != null; } - Future refreshGood() async { + Future> getCategories( {required int page, String? query, required int perpage}) async { + List list = []; try { - int? appCompanyId = Redux.store!.state.userState!.auth!.companyId; - Response categories = await _api.dictionaries('/goods'); - if (categories.operation! && categories.list!.isNotEmpty) { - for (final dynamic map in categories.list!) { - final GoodResponse good = GoodResponse.fromMap(map); - final Good entity = new Good() - ..id = good.id - ..name = good.name - ..categoryId = good.categoryId - ..ean = good.ean - ..articul = good.articul - ..price = good.price - ..optPrice = good.optPrice - ..basePrice = good.basePrice - ..divisible = good.divisible - ..updatedAt = good.updatedAt - ..appCompanyId = appCompanyId; - _db.insert(goodTableName, entity.toMap()); + final Map requestBody = { + 'page': page, + 'perpage': perpage, + 'filter': [ + {'col': 'name', 'action': 'like', 'val': query ?? ''} + ] + }; + + DictResponseEntity categories = + await _api.dictionaries('/goods_categories_get', requestBody: requestBody); + if (categories.original.data != null && + categories.original.data!.isNotEmpty) { + for (final dynamic map in categories.original.data!) { + final CategoryResponse good = CategoryResponse.fromMap(map); + list.add(good); } } } catch (e, stack) { - log.e('goods', e, stack); + log.e('getCategories', e, stack); } + return list; + } + + Future> getGoods( + {required int page, String? query, required int perpage}) async { + List list = []; + try { + final Map requestBody = { + 'page': page, + 'perpage': perpage, + 'filter': [ + {'col': 'name', 'action': 'like', 'val': query ?? ''} + ] + }; + + DictResponseEntity categories = + await _api.dictionaries('/goods_goods_get', requestBody: requestBody); + if (categories.original.data != null && + categories.original.data!.isNotEmpty) { + for (final dynamic map in categories.original.data!) { + final GoodResponse good = GoodResponse.fromMap(map); + list.add(good); + } + } + } catch (e, stack) { + log.e('getGoods', e, stack); + } + return list; + } + + Future> getContragents( + {int? page, int? perpage, String? query}) async { + final List list = []; + try { + final Map requestBody = { + 'page': page, + 'perpage': perpage, + 'filter': [ + {'col': 'name', 'action': 'like', 'val': query ?? ''} + ] + }; + final DictResponseEntity contragents = await _api + .dictionaries('/general_contragents_get', requestBody: requestBody); + if (contragents.original.data != null) { + if (contragents.original.data!.isNotEmpty) { + for (dynamic map in contragents.original.data!) { + list.add(ContragentResponseEntity.fromJson(map)); + } + } + } + } catch (e, stack) { + log.e('getContragents', e, stack); + } + return list; + } + + Future saveContragent(ContragentResponseEntity contragent) async { + DictResponseEntity? status; + if (contragent.id != null) { + status = await _api.dictionarySave( + '/general_contragents_edit', contragent.toJson()); + } else { + status = await _api.dictionarySave( + '/general_contragents_add', contragent.toJson()); + } + String? message = getErrorMsg(status); + + return message; + } + + Future deleteContragent(ContragentResponseEntity contragent) async { + DictResponseEntity status = await _api.dictionarySave( + '/general_contragents_delete', contragent.toJson()); + String? message = getErrorMsg(status); + return message; + } + + String? getErrorMsg(DictResponseEntity status) { + String? message; + + if (status.exception != null) { + message = status.exception; + } else if (status.original.message != null) { + message = status.original.message; + } else if (status.original.errors != null) { + Map> errors = status.original.errors!; + errors.values.forEach((element) { + message = '${message ?? ''} \n ${element.join(',')}'; + }); + } + return message; } } diff --git a/lib/core/services/navigator_service.dart b/lib/core/services/navigator_service.dart index 255389d..a397f69 100644 --- a/lib/core/services/navigator_service.dart +++ b/lib/core/services/navigator_service.dart @@ -14,11 +14,11 @@ class NavigatorService extends BaseService { Future replace(String routeName, {dynamic arguments}) { log.d('routeName: $routeName'); - return navigatorKey.currentState! - .pushNamedAndRemoveUntil(routeName, (Route route) => false, arguments: arguments); + return navigatorKey.currentState!.pushNamedAndRemoveUntil( + routeName, (Route route) => false, + arguments: arguments); } - Future navigateToPage(MaterialPageRoute pageRoute) async { log.d('navigateToPage: pageRoute: ${pageRoute.settings.name}'); if (navigatorKey.currentState == null) { @@ -31,7 +31,7 @@ class NavigatorService extends BaseService { Future navigateToPageWithReplacement( MaterialPageRoute pageRoute) async { log.d('navigateToPageWithReplacement: ' - 'pageRoute: ${pageRoute.settings.name}'); + 'pageRoute: ${pageRoute.settings.name}'); if (navigatorKey.currentState == null) { log.e('navigateToPageWithReplacement: Navigator State is null'); return null; @@ -47,4 +47,4 @@ class NavigatorService extends BaseService { } navigatorKey.currentState!.pop(result); } -} \ No newline at end of file +} diff --git a/lib/core/utils/logger.dart b/lib/core/utils/logger.dart index 96b208b..f2a42e0 100644 --- a/lib/core/utils/logger.dart +++ b/lib/core/utils/logger.dart @@ -2,10 +2,10 @@ import 'dart:convert'; import 'package:logger/logger.dart'; class SimpleLogPrinter extends LogPrinter { + SimpleLogPrinter(this.className); final String className; static final _deviceStackTraceRegex = RegExp(r'#[0-9]+[\s]+(.+) \(([^\s]+)\)'); static final _webStackTraceRegex = RegExp(r'^((packages|dart-sdk)\/[^\s]+\/)'); - SimpleLogPrinter(this.className); @override List log(LogEvent event) { diff --git a/lib/routes/route_names.dart b/lib/routes/route_names.dart index a8451e2..47d8710 100644 --- a/lib/routes/route_names.dart +++ b/lib/routes/route_names.dart @@ -10,8 +10,6 @@ const String addByBarcodeViewRoute = 'AddByBarcodeView'; const String paymentViewRoute = 'paymentViewRoute'; const String receiptViewRoute = 'receiptViewRoute'; - - // dictionaries - category const String categoryEditRoute = 'categoryEditRoute'; const String categorySelectViewRoute = 'categorySelectViewRoute'; @@ -20,10 +18,13 @@ const String goodsEditRoute = 'goodsEditRoute'; const String goodsDictionaryViewRoute = 'goodsDictionaryViewRoute'; //dictionaries - contragent const String contragentSelectViewRoute = 'ContragentSelectViewRoute'; - +const String contragentEditRoute = 'contragentEditRoute'; // setting - ble printer const String settingPrinterBluetoothViewRoute = 'SettingPrinterBluetoothView'; -const String settingPrinterBluetoothSelectViewRoute = 'settingPrinterBluetoothSelectViewRoute'; -const String settingPrinterPaperSizeViewRoute = 'settingPrinterPaperSizeViewRoute'; -const String settingPrinterEncodingViewRoute = 'settingPrinterEncodingViewRoute'; +const String settingPrinterBluetoothSelectViewRoute = + 'settingPrinterBluetoothSelectViewRoute'; +const String settingPrinterPaperSizeViewRoute = + 'settingPrinterPaperSizeViewRoute'; +const String settingPrinterEncodingViewRoute = + 'settingPrinterEncodingViewRoute'; diff --git a/lib/routes/router.dart b/lib/routes/router.dart index 4d25d66..da8324b 100644 --- a/lib/routes/router.dart +++ b/lib/routes/router.dart @@ -1,9 +1,12 @@ import 'package:flutter/material.dart'; +import 'package:satu/core/models/dictionary/category_response.dart'; import 'package:satu/core/models/dictionary/category_row_data.dart'; +import 'package:satu/core/models/dictionary/contragent/contragent_response_entity.dart'; +import 'package:satu/core/models/dictionary/good_response.dart'; import 'package:satu/core/models/dictionary/good_row_data.dart'; -import 'package:satu/core/models/entity_data/transaction_data.dart'; import 'package:satu/views/dictionaries/category/category_edit.dart'; import 'package:satu/views/dictionaries/category/category_select_view.dart'; +import 'package:satu/views/dictionaries/contragents/contragents_edit.dart'; import 'package:satu/views/dictionaries/goods/goods_edit.dart'; import 'package:satu/views/login/login_view.dart'; import 'package:satu/views/main/main_view.dart'; @@ -73,13 +76,20 @@ Route generateRoute(RouteSettings settings) { routeName: settings.name, viewToShow: SelectContragentView(), ); + case contragentEditRoute: + final ContragentResponseEntity contragent = + settings.arguments! as ContragentResponseEntity; + return _getPageRoute( + routeName: settings.name, + viewToShow: ContragentEdit(contragent: contragent), + ); case paymentViewRoute: return _getPageRoute( routeName: settings.name, viewToShow: const PaymentView(), ); case categoryEditRoute: - final CategoryRowDao category = settings.arguments! as CategoryRowDao; + final CategoryResponse category = settings.arguments! as CategoryResponse; return _getPageRoute( routeName: settings.name, viewToShow: CategoryEdit( @@ -92,7 +102,7 @@ Route generateRoute(RouteSettings settings) { viewToShow: CategorySelectView(), ); case goodsEditRoute: - final GoodRowDao good = settings.arguments! as GoodRowDao; + final GoodResponse good = settings.arguments! as GoodResponse; return _getPageRoute( routeName: settings.name, viewToShow: GoodEdit( diff --git a/lib/views/dictionaries/category/category_edit.dart b/lib/views/dictionaries/category/category_edit.dart index b7ba197..ec10884 100644 --- a/lib/views/dictionaries/category/category_edit.dart +++ b/lib/views/dictionaries/category/category_edit.dart @@ -2,6 +2,7 @@ import 'package:flutter/material.dart'; import 'package:logger/logger.dart'; import 'package:satu/core/entity/category_entity.dart'; import 'package:satu/core/models/dialog_models.dart'; +import 'package:satu/core/models/dictionary/category_response.dart'; import 'package:satu/core/models/dictionary/category_row_data.dart'; import 'package:satu/core/services/dialog_service.dart'; import 'package:satu/core/services/dictionary_service.dart'; @@ -10,19 +11,17 @@ import 'package:satu/core/utils/locator.dart'; import 'package:satu/core/utils/logger.dart'; import 'package:satu/routes/route_names.dart'; import 'package:satu/shared/ui_helpers.dart'; -import 'package:satu/views/dictionaries/category/category_view.dart'; import 'package:satu/widgets/bar/products_app_bar.dart'; import 'package:satu/widgets/buttons/busy_button.dart'; import 'package:satu/widgets/fields/input_field.dart'; import 'package:satu/widgets/fields/line_tile.dart'; -import 'package:satu/widgets/fields/note_text.dart'; class CategoryEdit extends StatefulWidget { const CategoryEdit({ required this.category, Key? key, }) : super(key: key); - final CategoryRowDao category; + final CategoryResponse category; @override _CategoryEditState createState() => _CategoryEditState(); @@ -35,18 +34,17 @@ class _CategoryEditState extends State { final Logger log = getLogger('_CategoryEditState'); late TextEditingController _controller; - String parentCategoryName = ''; - int parentCategoryId = 0; + String? parentCategoryName; + int? parentCategoryId; @override void initState() { super.initState(); if (widget.category.parentId != null) { - parentCategoryId = widget.category.parentId!; + parentCategoryId = widget.category.parentId; + parentCategoryName = widget.category.parentId.toString(); } _controller = TextEditingController(text: widget.category.name); - - getAndStateCategoryName(parentCategoryId); } @override @@ -55,24 +53,7 @@ class _CategoryEditState extends State { super.dispose(); } - Future getAndStateCategoryName(int id) async { - String name = ''; - if (id == 0) { - name = 'Корневая категория'; - } else { - log.i('message $id'); - final Category? category = await _dictionaryService.getCategoryById(id); - if (category != null) { - name = category.name; - } - log.i('message $name'); - } - setState(() { - parentCategoryName = name; - parentCategoryId = id; - }); - } @override Widget build(BuildContext context) { @@ -89,7 +70,7 @@ class _CategoryEditState extends State { children: [ verticalSpaceSmall, LineTile( - parentCategoryName, + parentCategoryName ?? 'Корневая категория', onTap: selectCategory, labelText: 'Родительская категория', ), @@ -133,8 +114,11 @@ class _CategoryEditState extends State { Future selectCategory() async { final dynamic result = await _navigatorService.push(categorySelectViewRoute); - if (result != null) { - getAndStateCategoryName(result as int); - } + CategoryResponse? category = result as CategoryResponse?; + setState(() { + parentCategoryId = category?.id; + parentCategoryName = category?.name; + }); + } } diff --git a/lib/views/dictionaries/category/category_select_view.dart b/lib/views/dictionaries/category/category_select_view.dart index 7edc166..c25be43 100644 --- a/lib/views/dictionaries/category/category_select_view.dart +++ b/lib/views/dictionaries/category/category_select_view.dart @@ -1,13 +1,13 @@ +import 'dart:async'; + import 'package:flutter/material.dart'; +import 'package:infinite_scroll_pagination/infinite_scroll_pagination.dart'; import 'package:satu/core/entity/category_entity.dart'; -import 'package:satu/core/entity/goods_entity.dart'; +import 'package:satu/core/models/dictionary/category_response.dart'; import 'package:satu/core/models/dictionary/category_row_data.dart'; -import 'package:satu/core/redux/actions/sell_actions.dart'; -import 'package:satu/core/redux/store.dart'; import 'package:satu/core/services/dictionary_service.dart'; import 'package:satu/core/services/navigator_service.dart'; import 'package:satu/core/utils/locator.dart'; -import 'package:satu/routes/route_names.dart'; import 'package:satu/shared/app_colors.dart'; import 'package:satu/shared/ui_helpers.dart'; import 'package:satu/views/dictionaries/component/dictionary_list_tile.dart'; @@ -16,8 +16,6 @@ import 'package:satu/widgets/bar/products_title_bar.dart'; import 'package:satu/widgets/fields/input_field.dart'; import 'package:satu/widgets/fields/line_checkbox.dart'; -import 'category_view.dart'; - class CategorySelectView extends StatefulWidget { @override _CategorySelectViewState createState() => _CategorySelectViewState(); @@ -29,38 +27,41 @@ class _CategorySelectViewState extends State { late TextEditingController _searchTextController; final FocusNode _searchFocusNode = FocusNode(); - late List _categories = []; - - late List items = []; + static const _pageSize = 20; + String query = ''; + Timer? _debounce; + final PagingController _pagingController = + PagingController(firstPageKey: 1); @override void initState() { _searchTextController = TextEditingController(); _searchTextController.addListener(() { - if (_searchTextController.text.isNotEmpty) { - searchByField(_searchTextController.text); - } else { - reset(); - } + setState(() { + query = _searchTextController.text; + }); + if (_debounce?.isActive ?? false) _debounce?.cancel(); + _debounce = Timer(const Duration(milliseconds: 500), () { + _pagingController.refresh(); + }); + }); + _pagingController.addPageRequestListener((pageKey) { + _fetchData(pageKey, _pageSize, query); }); - initQuery(); super.initState(); } - Future initQuery() async { - _categories = await _dictionaryService.getCategoriesAll(); - searchByField(''); - } - @override void dispose() { + _debounce?.cancel(); + _pagingController.dispose(); _searchTextController.dispose(); _searchFocusNode.dispose(); super.dispose(); } - Future handlerCategory(int id) async { - _navigatorService.pop(id); + Future handlerCategory(CategoryResponse? category) async { + _navigatorService.pop(category); } @override @@ -82,43 +83,47 @@ class _CategorySelectViewState extends State { 'Корневая категория', value: true, labelText: 'По умолчанию', - onTap: () => handlerCategory(0), + onTap: () => handlerCategory(null), ), const ProductsTitleBarBar(title: 'Выберите категорию'), Expanded( - child: ListView.separated( + child: PagedListView.separated( physics: const BouncingScrollPhysics(), - itemCount: items.length, - itemBuilder: (BuildContext context, int index) { - final CategoryRowDao category = items[index]; - return DictionaryTile( - key: Key('category_${category.id}'), - onPress: () => handlerCategory(category.id!), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - category.name, - style: const TextStyle(fontSize: 12, color: textColor), - ), - Text( - category.parentName.isEmpty - ? 'Корневая категория' - : 'Родитель: ${category.parentName}', - style: const TextStyle( - fontSize: 10, color: placeholderColor)), - ], - ), - ); - }, separatorBuilder: (BuildContext context, int index) { return const Divider( height: 1.0, color: disableColor, ); }, + pagingController: _pagingController, + builderDelegate: PagedChildBuilderDelegate( + itemBuilder: (BuildContext context, CategoryResponse category, + int index) { + return DictionaryTile( + key: Key('category_${category.id}'), + onPress: () => handlerCategory(category), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + category.name, + style: + const TextStyle(fontSize: 12, color: textColor), + ), + Text( + category.parentId == null + ? 'Корневая категория' + : 'Родитель: ${category.parentId}', + style: const TextStyle( + fontSize: 10, color: placeholderColor)), + ], + ), + ); + }, + ), ), - ), + ) + ], ), ); @@ -126,28 +131,18 @@ class _CategorySelectViewState extends State { void reset() { _searchTextController.clear(); - searchByField(''); } - void searchByField(String query) async { - final List list = []; - final Iterable filtered = query == '' - ? _categories - : _categories.where((element) => - element.name.toLowerCase().contains(query.toLowerCase())); - filtered.forEach((element) { - final Category category = _categories - .firstWhere((parent) => parent.id == element.parentId, orElse: () { - return Category(); - }); - final String parentName = category.name; - final CategoryRowDao rowDao = CategoryRowDao( - element.name, parentName, element.id, - parentId: element.parentId); - list.add(rowDao); - }); - setState(() { - items = list; - }); + Future _fetchData(int pageKey, int perPage, String? query) async { + final List newItems = await _dictionaryService + .getCategories(page: pageKey, query: query, perpage: perPage); + + final isLastPage = newItems.length < _pageSize; + if (isLastPage) { + _pagingController.appendLastPage(newItems); + } else { + final nextPageKey = pageKey + 1; + _pagingController.appendPage(newItems, nextPageKey); + } } } diff --git a/lib/views/dictionaries/category/category_view.dart b/lib/views/dictionaries/category/category_view.dart index bab2f00..8cf8e13 100644 --- a/lib/views/dictionaries/category/category_view.dart +++ b/lib/views/dictionaries/category/category_view.dart @@ -1,15 +1,16 @@ +import 'dart:async'; + import 'package:flutter/material.dart'; +import 'package:infinite_scroll_pagination/infinite_scroll_pagination.dart'; import 'package:satu/core/entity/category_entity.dart'; -import 'package:satu/core/entity/goods_entity.dart'; +import 'package:satu/core/models/dictionary/category_response.dart'; import 'package:satu/core/models/dictionary/category_row_data.dart'; import 'package:satu/core/redux/actions/sell_actions.dart'; -import 'package:satu/core/redux/store.dart'; import 'package:satu/core/services/dictionary_service.dart'; import 'package:satu/core/services/navigator_service.dart'; import 'package:satu/core/utils/locator.dart'; import 'package:satu/routes/route_names.dart'; import 'package:satu/shared/app_colors.dart'; -import 'package:satu/shared/ui_helpers.dart'; import 'package:satu/views/dictionaries/component/dictionary_list_tile.dart'; import 'package:satu/widgets/bar/products_app_bar.dart'; import 'package:satu/widgets/bar/products_title_bar.dart'; @@ -26,31 +27,36 @@ class _CategoryDictionaryViewState extends State { late TextEditingController _searchTextController; final FocusNode _searchFocusNode = new FocusNode(); - late List _categories = []; - late List items = []; + static const _pageSize = 20; + String query = ''; + Timer? _debounce; + + final PagingController _pagingController = + PagingController(firstPageKey: 1); @override void initState() { _searchTextController = TextEditingController(); _searchTextController.addListener(() { - if (_searchTextController.text.isNotEmpty) { - searchByField(_searchTextController.text); - } else { - reset(); - } + setState(() { + query = _searchTextController.text; + }); + if (_debounce?.isActive ?? false) _debounce?.cancel(); + _debounce = Timer(const Duration(milliseconds: 500), () { + _pagingController.refresh(); + }); + }); + _pagingController.addPageRequestListener((pageKey) { + _fetchData(pageKey, _pageSize, query); }); - initQuery(); super.initState(); } - Future initQuery() async { - _categories = await _dictionaryService.getCategoriesAll(); - searchByField(''); - } - @override void dispose() { + _debounce?.cancel(); + _pagingController.dispose(); _searchTextController.dispose(); _searchFocusNode.dispose(); super.dispose(); @@ -73,40 +79,43 @@ class _CategoryDictionaryViewState extends State { ), const ProductsTitleBarBar(title: 'Список категории'), Expanded( - child: ListView.separated( + child: PagedListView.separated( physics: const BouncingScrollPhysics(), - itemCount: items.length, - itemBuilder: (BuildContext context, int index) { - final CategoryRowDao category = items[index]; - return DictionaryTile( - key: Key('category_${category.id}'), - onPress: () => _navigatorService.push(categoryEditRoute, - arguments: category), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - category.name, - style: const TextStyle(fontSize: 12, color: textColor), - ), - Text( - category.parentName.isEmpty - ? 'Корневая категория' - : 'Родитель: ${category.parentName}', - style: const TextStyle( - fontSize: 10, color: placeholderColor)), - ], - ), - ); - }, separatorBuilder: (BuildContext context, int index) { return const Divider( height: 1.0, color: disableColor, ); }, + pagingController: _pagingController, + builderDelegate: PagedChildBuilderDelegate( + itemBuilder: (BuildContext context, CategoryResponse category, + int index) { + return DictionaryTile( + key: Key('category_${category.id}'), + onPress: () => _navigatorService.push(categoryEditRoute, + arguments: category), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + category.name, + style: + const TextStyle(fontSize: 12, color: textColor), + ), + Text( + category.parentId ==null + ? 'Корневая категория' + : 'Родитель: ${category.parentId}', + style: const TextStyle( + fontSize: 10, color: placeholderColor)), + ], + ), + ); + }, + ), ), - ), + ) ], ), floatingActionButton: FloatingActionButton( @@ -124,30 +133,18 @@ class _CategoryDictionaryViewState extends State { void reset() { _searchTextController.clear(); - searchByField(''); } - void searchByField(String query) async { - log.i(query); - final List list = []; - final Iterable filtered = query == '' - ? _categories - : _categories.where((element) => - element.name.toLowerCase().contains(query.toLowerCase())); - filtered.forEach((element) { - final Category category = _categories - .firstWhere((parent) => parent.id == element.parentId, orElse: () { - return Category(); - }); - final String parentName = category.name; - final CategoryRowDao rowDao = CategoryRowDao( - element.name, parentName, element.id, - parentId: element.parentId); - list.add(rowDao); - }); - setState(() { - items = list; - }); + Future _fetchData(int pageKey, int perPage, String? query) async { + final List newItems = await _dictionaryService + .getCategories(page: pageKey, query: query, perpage: perPage); + + final isLastPage = newItems.length < _pageSize; + if (isLastPage) { + _pagingController.appendLastPage(newItems); + } else { + final nextPageKey = pageKey + 1; + _pagingController.appendPage(newItems, nextPageKey); + } } } - diff --git a/lib/views/dictionaries/contragents/contragents_edit.dart b/lib/views/dictionaries/contragents/contragents_edit.dart new file mode 100644 index 0000000..1aa546d --- /dev/null +++ b/lib/views/dictionaries/contragents/contragents_edit.dart @@ -0,0 +1,170 @@ +import 'package:flutter/material.dart'; +import 'package:logger/logger.dart'; +import 'package:satu/core/models/dialog_models.dart'; +import 'package:satu/core/models/dictionary/contragent/contragent_response_entity.dart'; +import 'package:satu/core/services/dialog_service.dart'; +import 'package:satu/core/services/dictionary_service.dart'; +import 'package:satu/core/services/navigator_service.dart'; +import 'package:satu/core/utils/locator.dart'; +import 'package:satu/core/utils/logger.dart'; +import 'package:satu/shared/ui_helpers.dart'; +import 'package:satu/widgets/bar/products_app_bar.dart'; +import 'package:satu/widgets/buttons/busy_button.dart'; +import 'package:satu/widgets/fields/input_checkbox.dart'; +import 'package:satu/widgets/fields/input_field.dart'; + +class ContragentEdit extends StatefulWidget { + const ContragentEdit({ + required this.contragent, + Key? key, + }) : super(key: key); + final ContragentResponseEntity contragent; + + @override + _ContragentEditState createState() => _ContragentEditState(); +} + +class _ContragentEditState extends State { + final NavigatorService _navigatorService = locator(); + final DictionaryService _dictionaryService = locator(); + final DialogService _dialogService = locator(); + final Logger log = getLogger('_GoodEditState'); + late TextEditingController _controllerName; + late TextEditingController _controllerBinIin; + late TextEditingController _controllerPhone; + late TextEditingController _controllerMail; + late bool _isNds; + late bool _isResident; + + String parentCategoryName = ''; + int? parentCategoryId; + + @override + void initState() { + super.initState(); + _controllerName = TextEditingController(text: widget.contragent.name ?? ''); + _controllerBinIin = + TextEditingController(text: widget.contragent.biniin ?? ''); + _controllerPhone = + TextEditingController(text: widget.contragent.phone ?? ''); + _controllerMail = + TextEditingController(text: widget.contragent.email ?? ''); + _isNds = widget.contragent.nds == 1; + _isResident = widget.contragent.resident == 1; + } + + @override + void dispose() { + _controllerName.dispose(); + super.dispose(); + } + + void save() async { + ContragentResponseEntity contragent = widget.contragent; + contragent.name = _controllerName.text; + contragent.biniin = _controllerBinIin.text; + contragent.phone = _controllerPhone.text; + contragent.email = _controllerMail.text; + contragent.nds = _isNds ? 1 : 0; + contragent.resident = _isResident ? 1 : 0; + String? message = await _dictionaryService.saveContragent(contragent); + if (message != null) { + _dialogService.showDialog(description: message); + } else { + _navigatorService.pop(true); + } + } + + void delete() async { + ContragentResponseEntity contragent = widget.contragent; + String? message = await _dictionaryService.deleteContragent(contragent); + if (message != null) { + _dialogService.showDialog(description: message); + } else { + _navigatorService.pop(true); + } + } + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: ProductsAppBar( + title: widget.contragent.id == null + ? 'Добавление контрагента' + : 'Редактирование контрагента', + ), + body: SingleChildScrollView( + physics: const BouncingScrollPhysics(), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + verticalSpaceSmall, + InputField( + controller: _controllerName, + labelText: 'Наименование', + placeholder: 'Введите наименование контрагента', + ), + InputField( + controller: _controllerBinIin, + labelText: 'БИН/ИИН>', + placeholder: 'Введите БИН/ИИН', + ), + InputField( + controller: _controllerPhone, + labelText: 'Телефон', + placeholder: 'Введите номер телефона', + ), + InputField( + controller: _controllerMail, + labelText: 'E-mail"', + placeholder: 'Введите электронную почту', + ), + InputCheckBox('НДС', value: _isNds, labelText: 'Плательщик НДС', + onChanged: (value) { + setState(() { + _isNds = value ?? false; + }); + }), + InputCheckBox('', value: _isResident, labelText: 'Резидент', + onChanged: (value) { + setState(() { + _isResident = value ?? false; + }); + }), + Padding( + padding: + const EdgeInsets.symmetric(horizontal: 45.0, vertical: 20.0), + child: BusyButton( + title: 'СОХРАНИТЬ', + onPressed: () { + save(); + }), + ), + if (widget.contragent.id != null) + Padding( + padding: const EdgeInsets.symmetric( + horizontal: 45.0, vertical: 20.0), + child: BusyButton( + title: 'УДАЛИТЬ', + onPressed: () async { + DialogResponse response = + await _dialogService.showConfirmationDialog( + title: 'Внимание', + description: + 'Вы уверены, что хотите удалить категорию?', + confirmationTitle: 'Удалить', + cancelTitle: 'Отмена'); + + if (response.confirmed) { + delete(); + } + }, + isDanger: true, + ), + ), + ], + ), + ), + ); + } +} diff --git a/lib/views/dictionaries/contragents/contragents_view.dart b/lib/views/dictionaries/contragents/contragents_view.dart new file mode 100644 index 0000000..4e1df98 --- /dev/null +++ b/lib/views/dictionaries/contragents/contragents_view.dart @@ -0,0 +1,141 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_svg/svg.dart'; +import 'package:infinite_scroll_pagination/infinite_scroll_pagination.dart'; +import 'package:satu/core/models/dictionary/contragent/contragent_response_entity.dart'; +import 'package:satu/core/models/dictionary/good_row_data.dart'; +import 'package:satu/core/redux/actions/sell_actions.dart'; +import 'package:satu/core/services/dictionary_service.dart'; +import 'package:satu/core/services/navigator_service.dart'; +import 'package:satu/core/utils/locator.dart'; +import 'package:satu/routes/route_names.dart'; +import 'package:satu/shared/app_colors.dart'; +import 'package:satu/views/dictionaries/component/dictionary_list_tile.dart'; +import 'package:satu/widgets/bar/products_app_bar.dart'; +import 'package:satu/widgets/bar/products_title_bar.dart'; +import 'package:satu/widgets/fields/input_field.dart'; + +class ContragentsDictionaryView extends StatefulWidget { + @override + _ContragentsDictionaryViewState createState() => + _ContragentsDictionaryViewState(); +} + +class _ContragentsDictionaryViewState extends State { + final DictionaryService _dictionaryService = locator(); + final NavigatorService _navigatorService = locator(); + late TextEditingController _searchTextController; + final FocusNode _searchFocusNode = FocusNode(); + + late List items = []; + static const _pageSize = 20; + + final PagingController _pagingController = + PagingController(firstPageKey: 0); + + @override + void initState() { + _searchTextController = TextEditingController(); + _searchTextController.addListener(() { + if (_searchTextController.text.isNotEmpty) { + //searchByField(_searchTextController.text); + } else { + reset(); + } + }); + _pagingController.addPageRequestListener((pageKey) { + _fetchData(pageKey, _pageSize, null); + }); + super.initState(); + } + + Future initQuery() async { + //searchByField(''); + } + + @override + void dispose() { + _searchTextController.dispose(); + _searchFocusNode.dispose(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: ProductsAppBar( + title: 'Контрагенты', + drawerShow: true, + ), + body: Column( + children: [ + InputField( + placeholder: 'Поиск по наименованию', + search: true, + controller: _searchTextController, + fieldFocusNode: _searchFocusNode, + ), + const ProductsTitleBarBar(title: 'Список контрагентов'), + Expanded( + child: PagedListView( + pagingController: _pagingController, + builderDelegate: + PagedChildBuilderDelegate( + itemBuilder: (BuildContext context, + ContragentResponseEntity entity, int index) { + return DictionaryTile( + key: Key('contragent_${entity.id}'), + onPress: () async { + final dynamic result = await _navigatorService + .push(contragentEditRoute, arguments: entity); + if (result != null && true == (result as bool)) { + //searchByField(''); + } + }, + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + entity.name ?? '', + style: const TextStyle(fontSize: 12, color: textColor), + ), + Text('БИН/ИИН: ${entity.biniin}', + style: const TextStyle( + fontSize: 10, color: placeholderColor)), + ], + ), + ); + }, + ), + )) + ], + ), + floatingActionButton: FloatingActionButton( + elevation: 2, + onPressed: () => locator().push(contragentEditRoute, + arguments: ContragentResponseEntity()..refAppCompanyTypeId = 5), + child: const Icon( + Icons.add_rounded, + size: 34.0, + color: whiteColor, + ), + ), + ); + } + + void reset() { + _searchTextController.clear(); + } + + Future _fetchData(int pageKey, int perPage, String? query) async { + final List newItems = await _dictionaryService + .getContragents(page: pageKey, query: query, perpage: perPage); + + final isLastPage = newItems.length < _pageSize; + if (isLastPage) { + _pagingController.appendLastPage(newItems); + } else { + final nextPageKey = pageKey + newItems.length; + _pagingController.appendPage(newItems, nextPageKey); + } + } +} diff --git a/lib/views/dictionaries/goods/goods_edit.dart b/lib/views/dictionaries/goods/goods_edit.dart index 32faa05..764a28b 100644 --- a/lib/views/dictionaries/goods/goods_edit.dart +++ b/lib/views/dictionaries/goods/goods_edit.dart @@ -2,7 +2,7 @@ import 'package:flutter/material.dart'; import 'package:logger/logger.dart'; import 'package:satu/core/entity/category_entity.dart'; import 'package:satu/core/models/dialog_models.dart'; -import 'package:satu/core/models/dictionary/category_row_data.dart'; +import 'package:satu/core/models/dictionary/good_response.dart'; import 'package:satu/core/models/dictionary/good_row_data.dart'; import 'package:satu/core/services/dialog_service.dart'; import 'package:satu/core/services/dictionary_service.dart'; @@ -11,19 +11,17 @@ import 'package:satu/core/utils/locator.dart'; import 'package:satu/core/utils/logger.dart'; import 'package:satu/routes/route_names.dart'; import 'package:satu/shared/ui_helpers.dart'; -import 'package:satu/views/dictionaries/category/category_view.dart'; import 'package:satu/widgets/bar/products_app_bar.dart'; import 'package:satu/widgets/buttons/busy_button.dart'; import 'package:satu/widgets/fields/input_field.dart'; import 'package:satu/widgets/fields/line_tile.dart'; -import 'package:satu/widgets/fields/note_text.dart'; class GoodEdit extends StatefulWidget { const GoodEdit({ required this.good, Key? key, }) : super(key: key); - final GoodRowDao good; + final GoodResponse good; @override _GoodEditState createState() => _GoodEditState(); @@ -44,10 +42,11 @@ class _GoodEditState extends State { super.initState(); if (widget.good.categoryId != null) { parentCategoryId = widget.good.categoryId; + parentCategoryName = widget.good.categoryName ?? ''; } _controller = TextEditingController(text: widget.good.name); - getAndStateCategoryName(parentCategoryId); + //getAndStateCategoryName(parentCategoryId); } @override @@ -56,22 +55,22 @@ class _GoodEditState extends State { super.dispose(); } - Future getAndStateCategoryName(int? id) async { - String name = ''; - if (id == null) { - } else if (id == 0) { - name = 'Корневая категория'; - } else { - final Category? category = await _dictionaryService.getCategoryById(id); - if (category != null) { - name = category.name; - } - } - setState(() { - parentCategoryName = name; - parentCategoryId = id; - }); - } + // Future getAndStateCategoryName(int? id) async { + // String name = ''; + // if (id == null) { + // } else if (id == 0) { + // name = 'Корневая категория'; + // } else { + // final Category? category = await _dictionaryService.getCategoryById(id); + // if (category != null) { + // name = category.name; + // } + // } + // setState(() { + // parentCategoryName = name; + // parentCategoryId = id; + // }); + // } @override Widget build(BuildContext context) { @@ -166,7 +165,7 @@ class _GoodEditState extends State { final dynamic result = await _navigatorService.push(categorySelectViewRoute); if (result != null) { - getAndStateCategoryName(result as int); + //getAndStateCategoryName(result as int); } } } diff --git a/lib/views/dictionaries/goods/goods_view.dart b/lib/views/dictionaries/goods/goods_view.dart index ceb80f5..eb385ec 100644 --- a/lib/views/dictionaries/goods/goods_view.dart +++ b/lib/views/dictionaries/goods/goods_view.dart @@ -1,7 +1,11 @@ +import 'dart:async'; + import 'package:flutter/material.dart'; import 'package:flutter_svg/svg.dart'; +import 'package:infinite_scroll_pagination/infinite_scroll_pagination.dart'; import 'package:satu/core/entity/category_entity.dart'; import 'package:satu/core/entity/goods_entity.dart'; +import 'package:satu/core/models/dictionary/good_response.dart'; import 'package:satu/core/models/dictionary/good_row_data.dart'; import 'package:satu/core/redux/actions/sell_actions.dart'; import 'package:satu/core/services/dictionary_service.dart'; @@ -25,33 +29,35 @@ class _GoodsDictionaryViewState extends State { final NavigatorService _navigatorService = locator(); late TextEditingController _searchTextController; final FocusNode _searchFocusNode = FocusNode(); + static const _pageSize = 20; + String query = ''; + Timer? _debounce; - late List _goods = []; - late List _categories = []; - late List items = []; + final PagingController _pagingController = + PagingController(firstPageKey: 1); @override void initState() { _searchTextController = TextEditingController(); _searchTextController.addListener(() { - if (_searchTextController.text.isNotEmpty) { - searchByField(_searchTextController.text); - } else { - reset(); - } + setState(() { + query = _searchTextController.text; + }); + if (_debounce?.isActive ?? false) _debounce?.cancel(); + _debounce = Timer(const Duration(milliseconds: 500), () { + _pagingController.refresh(); + }); + }); + _pagingController.addPageRequestListener((pageKey) { + _fetchData(pageKey, _pageSize, query); }); - initQuery(); super.initState(); } - Future initQuery() async { - _goods = await _dictionaryService.getGoodsByNameOrEan(''); - _categories = await _dictionaryService.getCategoriesAll(); - searchByField(''); - } - @override void dispose() { + _debounce?.cancel(); + _pagingController.dispose(); _searchTextController.dispose(); _searchFocusNode.dispose(); super.dispose(); @@ -94,37 +100,40 @@ class _GoodsDictionaryViewState extends State { ), const ProductsTitleBarBar(title: 'Список товаров'), Expanded( - child: ListView.separated( - physics: const BouncingScrollPhysics(), - itemCount: items.length, - itemBuilder: (BuildContext context, int index) { - final GoodRowDao good = items[index]; - return DictionaryTile( - onPress: () { - locator() - .push(goodsEditRoute, arguments: good); + child: PagedListView.separated( + physics: const BouncingScrollPhysics(), + separatorBuilder: (BuildContext context, int index) { + return const Divider( + height: 1.0, + color: disableColor, + ); + }, + pagingController: _pagingController, + builderDelegate: PagedChildBuilderDelegate( + itemBuilder: + (BuildContext context, GoodResponse good, int index) { + return DictionaryTile( + onPress: () { + locator() + .push(goodsEditRoute, arguments: good); + }, + child: ProductTitleWidget( + name: good.name, + categoryName: good.categoryName, + ean: good.ean, + ), + ); }, - child: ProductTitleWidget( - name: good.name, - categoryName: good.categoryName, - ean: good.ean, - ), - ); - }, - separatorBuilder: (BuildContext context, int index) { - return const Divider( - height: 1.0, - color: disableColor, - ); - }, - ), - ), + ), + ), + ) ], ), floatingActionButton: FloatingActionButton( elevation: 2, - onPressed: () => locator() - .push(goodsEditRoute, arguments: GoodRowDao('', '')), + onPressed: () => + locator() + .push(goodsEditRoute, arguments: GoodRowDao('', '')), child: const Icon( Icons.add_rounded, size: 34.0, @@ -136,30 +145,18 @@ class _GoodsDictionaryViewState extends State { void reset() { _searchTextController.clear(); - searchByField(''); } - Future searchByField(String query) async { - log.i(query); - final List list = []; - final Iterable filtered = query == '' - ? _goods - : _goods.where((element) => - element.name.toLowerCase().contains(query.toLowerCase()) || - (element.ean != null && - element.ean!.contains(query.toLowerCase()))); - filtered.forEach((element) { - final Category category = _categories - .firstWhere((parent) => parent.id == element.categoryId, orElse: () { - return Category(); - }); - final String parentName = category.name; - final GoodRowDao rowDao = GoodRowDao(element.name, parentName, - ean: element.ean, id: element.id, categoryId: element.categoryId); - list.add(rowDao); - }); - setState(() { - items = list; - }); + Future _fetchData(int pageKey, int perPage, String? query) async { + final List newItems = await _dictionaryService.getGoods( + page: pageKey, query: query, perpage: perPage); + + final isLastPage = newItems.length < _pageSize; + if (isLastPage) { + _pagingController.appendLastPage(newItems); + } else { + final nextPageKey = pageKey + 1; + _pagingController.appendPage(newItems, nextPageKey); + } } } diff --git a/lib/views/login/login_view.dart b/lib/views/login/login_view.dart index 7b47ae1..fbe2776 100644 --- a/lib/views/login/login_view.dart +++ b/lib/views/login/login_view.dart @@ -1,6 +1,3 @@ -import 'dart:ui'; - -import 'package:flutter/services.dart'; import 'package:flutter_redux/flutter_redux.dart'; import 'package:flutter/material.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; @@ -12,7 +9,6 @@ import 'package:satu/core/services/dialog_service.dart'; import 'package:satu/core/services/navigator_service.dart'; import 'package:satu/core/utils/locator.dart'; import 'package:satu/routes/route_names.dart'; -import 'package:satu/shared/app_colors.dart'; import 'package:satu/shared/ui_helpers.dart'; import 'package:satu/widgets/buttons/busy_button.dart'; import 'package:satu/widgets/fields/input_field.dart'; @@ -52,57 +48,55 @@ class _LoginViewState extends State { return StoreConnector( converter: (store) => store.state.userState!, builder: (context, vm) { - return Scaffold( - body: LayoutBuilder( - builder: (context, constraints) { - return SingleChildScrollView( - child: ConstrainedBox( - constraints: BoxConstraints(minHeight: constraints.maxHeight), - child: Column( - mainAxisSize: MainAxisSize.max, - mainAxisAlignment: MainAxisAlignment.center, - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - const LogoSatu(), - InputField( - placeholder: 'Введите почту', - controller: emailController, - textInputType: TextInputType.emailAddress, - nextFocusNode: passwordNode, - ), - verticalSpaceSmall, - InputField( - placeholder: 'Введите пароль', - password: true, - controller: passwordController, - fieldFocusNode: passwordNode, - enterPressed: _pressBtnEnter, - textInputAction: TextInputAction.done, - ), - verticalSpaceMedium, - Padding( - padding: - EdgeInsets.only(left: 45.sp, right: 45.sp, top: 30.sp), - child: BusyButton( - title: 'ВОЙТИ', - busy: vm.isLoading!, - onPressed: _pressBtnEnter, - ), - ), - verticalSpaceLarge, - IconButton( - icon: const Icon(MdiIcons.qrcodeScan), - iconSize: ScreenUtil().setSp(40.0), - tooltip: 'Scan', - onPressed: scan, - ) - ], + return Scaffold(body: LayoutBuilder( + builder: (context, constraints) { + return SingleChildScrollView( + child: ConstrainedBox( + constraints: BoxConstraints(minHeight: constraints.maxHeight), + child: Column( + mainAxisSize: MainAxisSize.max, + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + const LogoSatu(), + InputField( + placeholder: 'Введите почту', + controller: emailController, + textInputType: TextInputType.emailAddress, + nextFocusNode: passwordNode, ), - ), - ); - }, - - )); + verticalSpaceSmall, + InputField( + placeholder: 'Введите пароль', + password: true, + controller: passwordController, + fieldFocusNode: passwordNode, + enterPressed: _pressBtnEnter, + textInputAction: TextInputAction.done, + ), + verticalSpaceMedium, + Padding( + padding: EdgeInsets.only( + left: 45.sp, right: 45.sp, top: 30.sp), + child: BusyButton( + title: 'ВОЙТИ', + busy: vm.isLoading!, + onPressed: _pressBtnEnter, + ), + ), + verticalSpaceLarge, + IconButton( + icon: const Icon(MdiIcons.qrcodeScan), + iconSize: ScreenUtil().setSp(40.0), + tooltip: 'Scan', + onPressed: scan, + ) + ], + ), + ), + ); + }, + )); }); } @@ -121,43 +115,14 @@ class _LoginViewState extends State { _dialogService.showDialog(description: 'Не верный формат QR кода'); } } - - // try { - // var options = ScanOptions(strings: { - // "cancel": 'Отмена', - // "flash_on": 'Вкл фонарик', - // "flash_off": 'Выкл фонарик', - // }); - // var result = await BarcodeScanner.scan(options: options); - // print(result.type); // The result type (barcode, cancelled, failed) - // print(result.rawContent); // The barcode content - // print(result.format); // The barcode format (as enum) - // print(result.formatNote); // If a unknown format was scanned this field contains a note - // if (result.type == ResultType.Barcode && result.rawContent?.length == 60) { - // //Redux.store.dispatch(authenticateToken(result.rawContent)); - // } else if (result.type == ResultType.Error) { - // _dialogService.showDialog(description: 'Не верный формат QR кода'); - // } - // } on PlatformException catch (e) { - // var result = ScanResult.create(); - // result.type = ResultType.Error; - // result.format = BarcodeFormat.unknown; - // if (e.code == BarcodeScanner.cameraAccessDenied) { - // result.rawContent = 'The user did not grant the camera permission!'; - // _dialogService.showDialog(description: 'Нет доступа до камеры устройства'); - // } else { - // result.rawContent = 'Unknown error: $e'; - // _dialogService.showDialog(description: 'Неизвестная ошибка: $e'); - // } - // } } } class LoginModel { + LoginModel( + {required this.authType, required this.login, required this.password}); + final String authType; final String login; final String password; - - LoginModel( - {required this.authType, required this.login, required this.password}); } diff --git a/lib/views/main/main_view.dart b/lib/views/main/main_view.dart index c7a3d2d..15fec45 100644 --- a/lib/views/main/main_view.dart +++ b/lib/views/main/main_view.dart @@ -7,11 +7,12 @@ import 'package:satu/core/utils/locator.dart'; import 'package:satu/views/analytics/analytics_view.dart'; import 'package:satu/views/dictionaries/category/category_view.dart'; import 'package:satu/views/dictionaries/goods/goods_view.dart'; -import 'package:satu/views/settings/printer_bluetooth/printer_view.dart'; import 'package:satu/views/settings/setting_view.dart'; import 'package:satu/views/work/work_view.dart'; import 'package:satu/widgets/drawer/app_drawer.dart'; +import '../dictionaries/contragents/contragents_view.dart'; + class MainView extends StatefulWidget { @override _MainViewState createState() => _MainViewState(); @@ -25,6 +26,7 @@ class _MainViewState extends State { final _settingsView = SettingsView(); final _categoryDictView = CategoryDictionaryView(); final _goodDictView = GoodsDictionaryView(); + final _contragentDictView = ContragentsDictionaryView(); final _analyticsView = const AnalyticsView(); Widget _body(Type viewClass) { @@ -40,6 +42,9 @@ class _MainViewState extends State { if(viewClass == GoodsDictionaryView) { return _goodDictView; } + if(viewClass == ContragentsDictionaryView) { + return _contragentDictView; + } if(viewClass == AnalyticsView) { return _analyticsView; } diff --git a/lib/views/settings/printer_bluetooth/printer_select.dart b/lib/views/settings/printer_bluetooth/printer_select.dart index 091fd6b..3200560 100644 --- a/lib/views/settings/printer_bluetooth/printer_select.dart +++ b/lib/views/settings/printer_bluetooth/printer_select.dart @@ -1,6 +1,3 @@ -import 'dart:async'; -import 'dart:convert'; -import 'dart:typed_data'; // import 'package:bluetooth_print/bluetooth_print.dart'; // import 'package:bluetooth_print/bluetooth_print_model.dart'; diff --git a/lib/views/settings/printer_bluetooth/printer_view.dart b/lib/views/settings/printer_bluetooth/printer_view.dart index a66046e..b487c39 100644 --- a/lib/views/settings/printer_bluetooth/printer_view.dart +++ b/lib/views/settings/printer_bluetooth/printer_view.dart @@ -1,4 +1,3 @@ -import 'dart:io'; import 'package:esc_pos_bluetooth/esc_pos_bluetooth.dart'; import 'package:flutter/material.dart'; diff --git a/lib/views/settings/setting_view.dart b/lib/views/settings/setting_view.dart index db3c8b2..902bfb2 100644 --- a/lib/views/settings/setting_view.dart +++ b/lib/views/settings/setting_view.dart @@ -2,7 +2,6 @@ import 'package:flutter/material.dart'; import 'package:satu/core/services/navigator_service.dart'; import 'package:satu/core/utils/locator.dart'; import 'package:satu/routes/route_names.dart'; -import 'package:satu/shared/app_colors.dart'; import 'package:satu/widgets/bar/products_app_bar.dart'; import 'package:satu/widgets/bar/products_title_bar.dart'; diff --git a/lib/views/start_up/start_up_view.dart b/lib/views/start_up/start_up_view.dart index 47d0359..bc88598 100644 --- a/lib/views/start_up/start_up_view.dart +++ b/lib/views/start_up/start_up_view.dart @@ -1,14 +1,11 @@ import 'package:flutter_redux/flutter_redux.dart'; import 'package:flutter/material.dart'; -import 'package:satu/core/models/auth/auth_response.dart'; import 'package:satu/core/redux/actions/user_actions.dart'; import 'package:satu/core/redux/state/user_state.dart'; import 'package:satu/core/redux/store.dart'; -import 'package:satu/core/services/api_service.dart'; import 'package:satu/core/services/navigator_service.dart'; import 'package:satu/core/utils/locator.dart'; -import 'package:satu/routes/route_names.dart'; import 'package:satu/shared/app_colors.dart'; @@ -19,7 +16,6 @@ class StartUpView extends StatefulWidget { class _StartUpViewState extends State { final NavigatorService _navigation = locator(); - final ApiService _api = locator(); @override void initState() { diff --git a/lib/views/work/tabs/buy_view.dart b/lib/views/work/tabs/buy_view.dart index 0f2e137..c5e8902 100644 --- a/lib/views/work/tabs/buy_view.dart +++ b/lib/views/work/tabs/buy_view.dart @@ -1,7 +1,4 @@ import 'package:flutter/material.dart'; -import 'package:satu/core/services/navigator_service.dart'; -import 'package:satu/core/utils/locator.dart'; -import 'package:satu/shared/shared_styles.dart'; import '../../../widgets/bar/products_app_bar.dart'; diff --git a/lib/views/work/tabs/component/contagent_select_bar.dart b/lib/views/work/tabs/component/contagent_select_bar.dart index a0d5369..5bb2bba 100644 --- a/lib/views/work/tabs/component/contagent_select_bar.dart +++ b/lib/views/work/tabs/component/contagent_select_bar.dart @@ -4,13 +4,11 @@ import 'package:satu/core/services/navigator_service.dart'; import 'package:satu/core/utils/locator.dart'; import 'package:satu/routes/route_names.dart'; import 'package:satu/shared/app_colors.dart'; -import 'package:satu/shared/shared_styles.dart'; -import 'package:satu/widgets/dialog/modal_select_dialog.dart'; class ContragentSelectBar extends StatelessWidget { - final String value; - const ContragentSelectBar({Key? key, required this.value}) : super(key: key); + const ContragentSelectBar({required this.value, Key? key}) : super(key: key); + final String value; @override Widget build(BuildContext context) { diff --git a/lib/views/work/tabs/component/custom_field.dart b/lib/views/work/tabs/component/custom_field.dart index 4d2c7df..a25fffe 100644 --- a/lib/views/work/tabs/component/custom_field.dart +++ b/lib/views/work/tabs/component/custom_field.dart @@ -2,12 +2,12 @@ import 'package:flutter/material.dart'; class CustomField extends StatelessWidget { + CustomField({@required this.hintText, @required this.iconData, this.label}); + final String? hintText; final IconData? iconData; final String? label; - CustomField({@required this.hintText, @required this.iconData, this.label}); - @override Widget build(BuildContext context) { return Container( diff --git a/lib/views/work/tabs/component/dialog_edit_product.dart b/lib/views/work/tabs/component/dialog_edit_product.dart index 4217ffc..9e4cc70 100644 --- a/lib/views/work/tabs/component/dialog_edit_product.dart +++ b/lib/views/work/tabs/component/dialog_edit_product.dart @@ -20,11 +20,11 @@ Future dialog(BuildContext cont) async { const Expanded( flex: 1, child: Text( - "Sample type", + 'Sample type', style: TextStyle(fontWeight: FontWeight.w700), ), ), - Expanded(flex: 1, child: Text("123")) + Expanded(flex: 1, child: Text('123')) ], ), ], diff --git a/lib/views/work/tabs/component/product_list_item.dart b/lib/views/work/tabs/component/product_list_item.dart index 6a1244a..402d2b2 100644 --- a/lib/views/work/tabs/component/product_list_item.dart +++ b/lib/views/work/tabs/component/product_list_item.dart @@ -1,6 +1,4 @@ -import 'dart:ffi'; -import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; import 'package:satu/core/models/dialog_models.dart'; @@ -15,7 +13,6 @@ import 'package:satu/shared/shared_styles.dart'; import 'package:satu/views/work/views/add_by_barcode/add_by_barcode_view.dart'; import 'package:satu/widgets/ui/product_title_widget.dart'; -import 'dialog_edit_product.dart'; class ProductListItem extends StatefulWidget { const ProductListItem( diff --git a/lib/views/work/tabs/component/transaction_item.dart b/lib/views/work/tabs/component/transaction_item.dart index 3a671a4..7ef2991 100644 --- a/lib/views/work/tabs/component/transaction_item.dart +++ b/lib/views/work/tabs/component/transaction_item.dart @@ -2,67 +2,61 @@ import 'package:flutter/material.dart'; class TransactionItem extends StatelessWidget { + TransactionItem( + {required this.fullName, + required this.status, + required this.amount, + required this.received}); final String fullName; final String status; final String amount; final bool received; - TransactionItem({required this.fullName, required this.status, required this.amount, required this.received}); - @override Widget build(BuildContext context) { return Container( margin: EdgeInsets.symmetric(vertical: 8), - child: Row( - children: [ - - Container( - width: 16, - height: 50, - //margin: EdgeInsets.only(right: 16), - // child: Icon( - // Icons.memory - // ), - ), - - Expanded( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - - Text( - fullName, - style: TextStyle( - //color: kPrimaryColor, - fontSize: 16, - fontWeight: FontWeight.bold, - ), - ), - - Text( - status, - style: TextStyle( - //color: kGreyColor, - fontSize: 12, - fontWeight: FontWeight.w500, - ), - ), - - ], + child: Row(children: [ + Container( + width: 16, + height: 50, + //margin: EdgeInsets.only(right: 16), + // child: Icon( + // Icons.memory + // ), + ), + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + fullName, + style: TextStyle( + //color: kPrimaryColor, + fontSize: 16, + fontWeight: FontWeight.bold, + ), ), - ), - - Text( - (received ? "+" : "-") + r" $ " + amount + " KZT", - style: TextStyle( - color: received ? Colors.green : Colors.red, - fontSize: 16, - fontWeight: FontWeight.bold, + Text( + status, + style: TextStyle( + //color: kGreyColor, + fontSize: 12, + fontWeight: FontWeight.w500, + ), ), - ), - - ] - ), + ], + ), + ), + Text( + (received ? '+' : '-') + r' $ ' + amount + ' KZT', + style: TextStyle( + color: received ? Colors.green : Colors.red, + fontSize: 16, + fontWeight: FontWeight.bold, + ), + ), + ]), ); } -} \ No newline at end of file +} diff --git a/lib/views/work/tabs/journal_view.dart b/lib/views/work/tabs/journal_view.dart index a6419ff..226346f 100644 --- a/lib/views/work/tabs/journal_view.dart +++ b/lib/views/work/tabs/journal_view.dart @@ -1,7 +1,6 @@ import 'package:flutter/material.dart'; import 'package:flutter_redux/flutter_redux.dart'; import 'package:grouped_list/grouped_list.dart'; -import 'package:satu/core/models/entity_data/transaction_data.dart'; import 'package:satu/core/models/flow/dao/transaction_dao.dart'; import 'package:satu/core/redux/actions/journal_actions.dart'; import 'package:satu/core/redux/state/journal_state.dart'; @@ -14,7 +13,6 @@ import 'package:satu/shared/app_colors.dart'; import 'package:satu/widgets/bar/products_app_bar.dart'; import 'package:satu/widgets/buttons/option_pill.dart'; import 'component/journal_list_tile.dart'; -import 'component/transaction_item.dart'; class JournalView extends StatefulWidget { @override diff --git a/lib/views/work/tabs/sell_view.dart b/lib/views/work/tabs/sell_view.dart index 5d47953..9a524b3 100644 --- a/lib/views/work/tabs/sell_view.dart +++ b/lib/views/work/tabs/sell_view.dart @@ -1,4 +1,3 @@ -import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:flutter_redux/flutter_redux.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; @@ -138,13 +137,13 @@ class SellView extends StatelessWidget { final dynamic result = await _nav.push(addByBarcodeViewRoute); if (result != null) { - final List goods = - await locator() - .getGoodsByEan(result as String); - if (goods.isNotEmpty) { - Redux.store - ?.dispatch(addSellItem(good: goods.first)); - } + // final List goods = + // await locator() + // .getGoodsByEan(result as String); + // if (goods.isNotEmpty) { + // Redux.store + // ?.dispatch(addSellItem(good: goods.first)); + // } } }, child: Icon(Icons.qr_code_rounded, diff --git a/lib/views/work/views/add_by_barcode/add_by_barcode_view.dart b/lib/views/work/views/add_by_barcode/add_by_barcode_view.dart index b57c79f..3a5998e 100644 --- a/lib/views/work/views/add_by_barcode/add_by_barcode_view.dart +++ b/lib/views/work/views/add_by_barcode/add_by_barcode_view.dart @@ -1,6 +1,4 @@ -import 'dart:io'; -import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:satu/core/services/navigator_service.dart'; import 'package:satu/core/utils/locator.dart'; diff --git a/lib/views/work/views/add_product/add_product_view.dart b/lib/views/work/views/add_product/add_product_view.dart index 7994aeb..51e866a 100644 --- a/lib/views/work/views/add_product/add_product_view.dart +++ b/lib/views/work/views/add_product/add_product_view.dart @@ -26,25 +26,21 @@ class _AddProductViewState extends State { late TextEditingController _searchTextController; final FocusNode _searchFocusNode = new FocusNode(); - List? _history; List? _categories; List? _goods; - @override void initState() { _searchTextController = TextEditingController(); _searchTextController.addListener(() { - if(_searchTextController.text.isNotEmpty){ - searchByField(_searchTextController.text); + if (_searchTextController.text.isNotEmpty) { + searchByField(_searchTextController.text); } else { - reset(); + reset(); } }); - _history = [Category() - ..id = 0 - ]; + _history = [Category()..id = 0]; _categories = []; _goods = []; super.initState(); @@ -63,15 +59,21 @@ class _AddProductViewState extends State { int catSize = _categories?.length ?? 0; int goodSize = _goods?.length ?? 0; return Scaffold( - appBar: ProductsAppBar( title: 'Категория',), + appBar: ProductsAppBar( + title: 'Категория', + ), body: Column( children: [ - InputField(placeholder: 'Поиск по наименованию или коду товара', + InputField( + placeholder: 'Поиск по наименованию или коду товара', search: true, controller: _searchTextController, - fieldFocusNode: _searchFocusNode,), + fieldFocusNode: _searchFocusNode, + ), verticalSpaceTiny, - ProductsTitleBarBar(title: goodSize > 0 ? 'Выберите товар' : 'Выберите категорию',), + ProductsTitleBarBar( + title: goodSize > 0 ? 'Выберите товар' : 'Выберите категорию', + ), Expanded( child: ListView.separated( physics: BouncingScrollPhysics(), @@ -94,14 +96,17 @@ class _AddProductViewState extends State { categoryName: _history?.last.name, onPress: () { onGoodPress(good); - } , + }, ); - }, separatorBuilder: (BuildContext context, int index) { - return Divider(height: 1.0, color: disableColor,); - }, + }, + separatorBuilder: (BuildContext context, int index) { + return Divider( + height: 1.0, + color: disableColor, + ); + }, ), ), - ], ), ); @@ -118,16 +123,16 @@ class _AddProductViewState extends State { } void reset() { - _history = [Category() - ..id = 0 - ]; - navigateCategory(0); - _searchTextController.clear(); - } + _history = [Category()..id = 0]; + navigateCategory(0); + _searchTextController.clear(); + } void navigateCategory(int categoryId) async { - List categories = await _dictionaryService.getCategoryByParentId(categoryId); - List goods = await _dictionaryService.getGoodsByCategoryId(categoryId); + List categories = + await _dictionaryService.getCategoryByParentId(categoryId); + List goods = + await _dictionaryService.getGoodsByCategoryId(categoryId); setState(() { _categories = categories; _goods = goods; @@ -142,5 +147,4 @@ class _AddProductViewState extends State { _goods = goods; }); } - } diff --git a/lib/views/work/views/add_product/component/add_category_list_item.dart b/lib/views/work/views/add_product/component/add_category_list_item.dart index 14dd02e..a287784 100644 --- a/lib/views/work/views/add_product/component/add_category_list_item.dart +++ b/lib/views/work/views/add_product/component/add_category_list_item.dart @@ -1,15 +1,12 @@ -import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:satu/shared/app_colors.dart'; -import 'package:satu/shared/shared_styles.dart'; -import 'package:satu/shared/ui_helpers.dart'; class AddCategoryListItem extends StatelessWidget { - final String name; - final Function? onPress; const AddCategoryListItem({Key? key, this.name = '', this.onPress}) : super(key: key); + final String name; + final Function? onPress; @override Widget build(BuildContext context) { diff --git a/lib/views/work/views/add_product/component/add_product_list_item.dart b/lib/views/work/views/add_product/component/add_product_list_item.dart index 0f3e4d4..4938b99 100644 --- a/lib/views/work/views/add_product/component/add_product_list_item.dart +++ b/lib/views/work/views/add_product/component/add_product_list_item.dart @@ -1,4 +1,3 @@ -import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; import 'package:satu/shared/app_colors.dart'; diff --git a/lib/views/work/views/contragent/companent/contragent_list_item.dart b/lib/views/work/views/contragent/companent/contragent_list_item.dart index 5e97493..4bff5ff 100644 --- a/lib/views/work/views/contragent/companent/contragent_list_item.dart +++ b/lib/views/work/views/contragent/companent/contragent_list_item.dart @@ -1,8 +1,5 @@ -import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:satu/shared/app_colors.dart'; -import 'package:satu/shared/shared_styles.dart'; -import 'package:satu/shared/ui_helpers.dart'; class ContragentListItem extends StatelessWidget { const ContragentListItem({Key? key, this.name, this.onPress}) diff --git a/lib/views/work/views/contragent/select_contragent_view.dart b/lib/views/work/views/contragent/select_contragent_view.dart index 11affe8..71fbcd0 100644 --- a/lib/views/work/views/contragent/select_contragent_view.dart +++ b/lib/views/work/views/contragent/select_contragent_view.dart @@ -1,14 +1,11 @@ import 'package:flutter/material.dart'; import 'package:satu/core/entity/category_entity.dart'; import 'package:satu/core/entity/goods_entity.dart'; -import 'package:satu/core/redux/actions/sell_actions.dart'; -import 'package:satu/core/redux/store.dart'; import 'package:satu/core/services/dictionary_service.dart'; import 'package:satu/core/services/navigator_service.dart'; import 'package:satu/core/utils/locator.dart'; import 'package:satu/shared/app_colors.dart'; import 'package:satu/shared/ui_helpers.dart'; -import 'package:satu/views/work/views/add_product/component/add_category_list_item.dart'; import 'package:satu/widgets/bar/products_app_bar.dart'; import 'package:satu/widgets/bar/products_title_bar.dart'; import 'package:satu/widgets/fields/input_field.dart'; diff --git a/lib/views/work/views/payment/component/combine_dock.dart b/lib/views/work/views/payment/component/combine_dock.dart index ee16749..41f2942 100644 --- a/lib/views/work/views/payment/component/combine_dock.dart +++ b/lib/views/work/views/payment/component/combine_dock.dart @@ -2,7 +2,6 @@ import 'package:flutter/material.dart'; import 'package:satu/core/utils/utils_parse.dart'; import 'package:satu/shared/app_colors.dart'; import 'package:satu/shared/ui_helpers.dart'; -import 'package:flutter_screenutil/flutter_screenutil.dart'; class CombineDock extends StatelessWidget { const CombineDock({ diff --git a/lib/views/work/views/payment/payment_view.dart b/lib/views/work/views/payment/payment_view.dart index 7bb4336..fc36f3d 100644 --- a/lib/views/work/views/payment/payment_view.dart +++ b/lib/views/work/views/payment/payment_view.dart @@ -1,7 +1,5 @@ -import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:flutter_redux/flutter_redux.dart'; -import 'package:satu/core/models/entity_data/transaction_data.dart'; import 'package:satu/core/redux/state/sell_state.dart'; import 'package:satu/core/redux/store.dart'; import 'package:satu/core/services/navigator_service.dart'; diff --git a/lib/views/work/views/receipt/receipt_view.dart b/lib/views/work/views/receipt/receipt_view.dart index 22feca0..09a8e2c 100644 --- a/lib/views/work/views/receipt/receipt_view.dart +++ b/lib/views/work/views/receipt/receipt_view.dart @@ -1,10 +1,7 @@ import 'dart:convert'; -import 'dart:io'; import 'package:esc_pos_bluetooth/esc_pos_bluetooth.dart'; import 'package:flutter/material.dart'; -import 'package:flutter_redux/flutter_redux.dart'; -import 'package:material_design_icons_flutter/material_design_icons_flutter.dart'; import 'package:satu/core/entity/transaction_entity.dart'; import 'package:satu/core/models/dialog_models.dart'; import 'package:satu/core/models/entity_data/transaction_data.dart'; diff --git a/lib/views/work/work_view.dart b/lib/views/work/work_view.dart index 0337d09..6b25e33 100644 --- a/lib/views/work/work_view.dart +++ b/lib/views/work/work_view.dart @@ -1,9 +1,7 @@ import 'package:flutter/material.dart'; -import 'package:material_design_icons_flutter/material_design_icons_flutter.dart'; import 'package:satu/core/redux/actions/sell_actions.dart'; import 'package:satu/core/redux/store.dart'; -import 'package:satu/shared/app_colors.dart'; import 'package:satu/views/work/tabs/buy_view.dart'; import 'package:satu/views/work/tabs/journal_view.dart'; import 'package:satu/views/work/tabs/sell_view.dart'; diff --git a/lib/widgets/bar/products_app_bar.dart b/lib/widgets/bar/products_app_bar.dart index 7d393bb..85bb055 100644 --- a/lib/widgets/bar/products_app_bar.dart +++ b/lib/widgets/bar/products_app_bar.dart @@ -2,16 +2,8 @@ import 'package:flutter/material.dart'; import 'package:satu/core/services/navigator_service.dart'; import 'package:satu/core/utils/locator.dart'; import 'package:satu/shared/app_colors.dart'; -import 'package:satu/widgets/bar/products_header_bar.dart'; class ProductsAppBar extends StatelessWidget implements PreferredSizeWidget { - final String? title; - final List? actions; - final Widget? child; - final double childHeight; - final double elevation; - final Color? backgroundColor; - final bool drawerShow; const ProductsAppBar( {Key? key, @@ -23,6 +15,13 @@ class ProductsAppBar extends StatelessWidget implements PreferredSizeWidget { this.drawerShow = false, this.backgroundColor = Colors.transparent}) : super(key: key); + final String? title; + final List? actions; + final Widget? child; + final double childHeight; + final double elevation; + final Color? backgroundColor; + final bool drawerShow; @override Widget build(BuildContext context) { diff --git a/lib/widgets/bar/products_header_bar.dart b/lib/widgets/bar/products_header_bar.dart index ba2f446..826084a 100644 --- a/lib/widgets/bar/products_header_bar.dart +++ b/lib/widgets/bar/products_header_bar.dart @@ -1,8 +1,5 @@ import 'package:flutter/material.dart'; -import 'package:flutter_screenutil/flutter_screenutil.dart'; import 'package:satu/shared/app_colors.dart'; -import 'package:satu/shared/shared_styles.dart'; -import 'package:satu/widgets/dialog/modal_select_dialog.dart'; class ProductHeaderBar extends StatelessWidget { const ProductHeaderBar({required this.count, required this.sum , Key? key}) diff --git a/lib/widgets/buttons/aman_icon_button.dart b/lib/widgets/buttons/aman_icon_button.dart index c140f26..0d8ec28 100644 --- a/lib/widgets/buttons/aman_icon_button.dart +++ b/lib/widgets/buttons/aman_icon_button.dart @@ -1,7 +1,5 @@ import 'package:auto_size_text/auto_size_text.dart'; import 'package:flutter/material.dart'; -import 'package:satu/shared/app_colors.dart'; -import 'package:satu/shared/shared_styles.dart'; /// A button that shows a busy indicator in place of title class AmanIconButton extends StatefulWidget { diff --git a/lib/widgets/buttons/busy_button.dart b/lib/widgets/buttons/busy_button.dart index 10eb081..9aa13c8 100644 --- a/lib/widgets/buttons/busy_button.dart +++ b/lib/widgets/buttons/busy_button.dart @@ -1,4 +1,3 @@ -import 'package:auto_size_text/auto_size_text.dart'; import 'package:flutter/material.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; import 'package:satu/shared/app_colors.dart'; @@ -6,6 +5,15 @@ import 'package:satu/shared/shared_styles.dart'; /// A button that shows a busy indicator in place of title class BusyButton extends StatefulWidget { + + const BusyButton({ + required this.title, + required this.onPressed, + this.busy = false, + this.enabled = true, + this.isCancel = false, + this.isDanger = false, + }); final bool busy; final String title; final Function onPressed; @@ -13,15 +21,6 @@ class BusyButton extends StatefulWidget { final bool isCancel; final bool isDanger; - const BusyButton({ - required this.title, - this.busy = false, - required this.onPressed, - this.enabled = true, - this.isCancel = false, - this.isDanger = false, - }); - @override _BusyButtonState createState() => _BusyButtonState(); } diff --git a/lib/widgets/dialog/dialog_manager.dart b/lib/widgets/dialog/dialog_manager.dart index 57b0b1d..e5cc659 100644 --- a/lib/widgets/dialog/dialog_manager.dart +++ b/lib/widgets/dialog/dialog_manager.dart @@ -1,21 +1,17 @@ -import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; -import 'package:flutter/services.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; -import 'package:mask_text_input_formatter/mask_text_input_formatter.dart'; import 'package:satu/core/models/dialog_models.dart'; import 'package:satu/core/services/dialog_service.dart'; import 'package:satu/core/utils/locator.dart'; import 'package:satu/shared/app_colors.dart'; import 'package:satu/shared/ui_helpers.dart'; import 'package:satu/widgets/buttons/busy_button.dart'; -import 'package:satu/widgets/fields/input_field.dart'; import 'package:satu/widgets/fields/input_field_rounded.dart'; class DialogManager extends StatefulWidget { - final Widget child; - DialogManager({Key? key, required this.child}) : super(key: key); + DialogManager({required this.child, Key? key}) : super(key: key); + final Widget child; _DialogManagerState createState() => _DialogManagerState(); } diff --git a/lib/widgets/dialog/modal_select_dialog.dart b/lib/widgets/dialog/modal_select_dialog.dart index c859031..4b2d7ee 100644 --- a/lib/widgets/dialog/modal_select_dialog.dart +++ b/lib/widgets/dialog/modal_select_dialog.dart @@ -1,12 +1,12 @@ import 'package:flutter/material.dart'; class DialogModalSelect extends StatefulWidget { - final String? title; - final String? descriptions; - final String? text; const DialogModalSelect({Key? key, this.title, this.descriptions, this.text}) : super(key: key); + final String? title; + final String? descriptions; + final String? text; @override _DialogModalSelectState createState() => _DialogModalSelectState(); @@ -86,7 +86,7 @@ class _DialogModalSelectState extends State { radius: avatarRadius, child: ClipRRect( borderRadius: BorderRadius.all(Radius.circular(avatarRadius)), - child: Image.asset("assets/model.jpeg")), + child: Image.asset('assets/model.jpeg')), ), ) ], diff --git a/lib/widgets/drawer/app_drawer.dart b/lib/widgets/drawer/app_drawer.dart index 1233348..390e496 100644 --- a/lib/widgets/drawer/app_drawer.dart +++ b/lib/widgets/drawer/app_drawer.dart @@ -1,4 +1,3 @@ -import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:flutter_redux/flutter_redux.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; @@ -12,6 +11,7 @@ import 'package:satu/shared/app_colors.dart'; import 'package:satu/shared/ui_helpers.dart'; import 'package:satu/views/analytics/analytics_view.dart'; import 'package:satu/views/dictionaries/category/category_view.dart'; +import 'package:satu/views/dictionaries/contragents/contragents_view.dart'; import 'package:satu/views/dictionaries/goods/goods_view.dart'; import 'package:satu/views/settings/setting_view.dart'; import 'package:satu/views/work/work_view.dart'; @@ -28,62 +28,95 @@ class AppDrawer extends StatelessWidget { _createHeader(), _createDrawerSectionTitle(text: 'ОСНОВНОЙ РАЗДЕЛ'), _createDrawerItem( - svgFile: 'sell', - text: 'Касса', - onTap: () { - Navigator.of(context).pop(); - Redux.store!.dispatch(navigateDrawer(WorkView)); - },), + svgFile: 'sell', + text: 'Касса', + onTap: () { + Navigator.of(context).pop(); + Redux.store!.dispatch(navigateDrawer(WorkView)); + }, + ), _createDrawerItem( - svgFile: 'analytics', + icon: Icons.analytics, text: 'Аналитика', onTap: () { Navigator.of(context).pop(); Redux.store!.dispatch(navigateDrawer(AnalyticsView)); - },), + }, + ), _createDrawerItem( - svgFile: 'inventarization', - text: 'Инвентаризация', - disable: true), + icon: Icons.archive, + text: 'Остатки', + onTap: () { + Navigator.of(context).pop(); + Redux.store!.dispatch(navigateDrawer(AnalyticsView)); + }, + disable: true, + ), + _createDrawerItem( + svgFile: 'inventarization', + text: 'Инвентаризация', + disable: true, + ), _createDrawerSectionTitle(text: 'СПРАВОЧНИКИ'), _createDrawerItem( - svgFile: 'categories', - text: 'Категории', - onTap: () { - Navigator.of(context).pop(); - Redux.store!.dispatch(navigateDrawer(CategoryDictionaryView)); - }), + svgFile: 'categories', + text: 'Категории', + onTap: () { + Navigator.of(context).pop(); + Redux.store!.dispatch(navigateDrawer(CategoryDictionaryView)); + }, + ), _createDrawerItem( - svgFile: 'goods', - text: 'Товары', - onTap: () { - Navigator.of(context).pop(); - Redux.store!.dispatch(navigateDrawer(GoodsDictionaryView)); - }), + svgFile: 'goods', + text: 'Товары', + onTap: () { + Navigator.of(context).pop(); + Redux.store!.dispatch(navigateDrawer(GoodsDictionaryView)); + }, + ), _createDrawerItem( - svgFile: 'contragents', text: 'Контрагенты', disable: true), + svgFile: 'contragents', + text: 'Контрагенты', + onTap: () { + Navigator.of(context).pop(); + Redux.store!.dispatch( + navigateDrawer(ContragentsDictionaryView) + ); + }, + ), _createDrawerSectionTitle(text: 'ИНФОРМАЦИЯ'), _createDrawerItem( - svgFile: 'question', text: 'Справочник', disable: true), + svgFile: 'question', + text: 'Справочник', + disable: true, + ), _createDrawerSectionTitle(text: 'ПРОЧЕЕ'), _createDrawerItem( - svgFile: 'settings', - text: 'Настройки', - onTap: () { - Navigator.of(context).pop(); - Redux.store!.dispatch(navigateDrawer(SettingsView)); - }), + svgFile: 'settings', + text: 'Настройки', + onTap: () { + Navigator.of(context).pop(); + Redux.store!.dispatch(navigateDrawer(SettingsView)); + }, + ), _createDrawerItem( - svgFile: 'global', text: 'Перейти на сайт', disable: true), + svgFile: 'global', + text: 'Перейти на сайт', + disable: true, + ), _createDrawerItem( - svgFile: 'bug', text: 'Сообщить об ошибке', disable: true), + svgFile: 'bug', + text: 'Сообщить об ошибке', + disable: true, + ), _createDrawerItem( - svgFile: 'logout', - text: 'Выйти из аккаунта', - isDanger: true, - onTap: () async { - Redux.store!.dispatch(logout); - }), + svgFile: 'logout', + text: 'Выйти из аккаунта', + isDanger: true, + onTap: () async { + Redux.store!.dispatch(logout); + }, + ), _createDrawerSectionTitle(text: ''), ], ), @@ -95,44 +128,60 @@ class AppDrawer extends StatelessWidget { return SizedBox( height: 180.h, child: DrawerHeader( - margin: EdgeInsets.zero, - padding: EdgeInsets.zero, - decoration: const BoxDecoration( - image: DecorationImage( - fit: BoxFit.cover, - image: AssetImage('assets/images/drawer/background.png'))), - child: Stack(children: [ + margin: EdgeInsets.zero, + padding: EdgeInsets.zero, + decoration: const BoxDecoration( + image: DecorationImage( + fit: BoxFit.cover, + image: AssetImage('assets/images/drawer/background.png'), + ), + ), + child: Stack( + children: [ Positioned( - bottom: 12.0, - left: 16.0, - child: Row( - children: [ - SizedBox( - height: 40, - width: 40, - child: Container( - decoration: const BoxDecoration( - image: DecorationImage( - fit: BoxFit.cover, - image: AssetImage( - 'assets/images/drawer/user.png')))), + bottom: 12.0, + left: 16.0, + child: Row( + children: [ + SizedBox( + height: 40, + width: 40, + child: Container( + decoration: const BoxDecoration( + image: DecorationImage( + fit: BoxFit.cover, + image: AssetImage( + 'assets/images/drawer/user.png', + ), + ), + ), ), - horizontalSpaceSmall, - StoreConnector( - converter: (store) => store.state.userState!, - builder: (context, snapshot) { - return Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text(snapshot.auth?.username ?? '', - style: TextStyle(fontSize: 16.0)), - Text('Продавец', style: TextStyle(fontSize: 12)), - ], - ); - }), - ], - )), - ])), + ), + horizontalSpaceSmall, + StoreConnector( + converter: (store) => store.state.userState!, + builder: (context, snapshot) { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + snapshot.auth?.username ?? '', + style: const TextStyle(fontSize: 16.0), + ), + const Text( + 'Продавец', + style: TextStyle(fontSize: 12), + ), + ], + ); + }, + ), + ], + ), + ), + ], + ), + ), ); } @@ -148,7 +197,7 @@ class AppDrawer extends StatelessWidget { child: Material( color: Colors.transparent, child: InkWell( - onTap: onTap, + onTap: disable ? () {} : onTap, child: Padding( padding: const EdgeInsets.symmetric(vertical: 15.0, horizontal: 20.0), @@ -180,12 +229,13 @@ class AppDrawer extends StatelessWidget { child: Text( text, style: TextStyle( - fontSize: 14.0, - color: disable - ? disableColor - : isDanger - ? dangerColor - : textColor), + fontSize: 14.0, + color: disable + ? disableColor + : isDanger + ? dangerColor + : textColor, + ), ), ) ], @@ -198,10 +248,11 @@ class AppDrawer extends StatelessWidget { Widget _createDrawerSectionTitle({required String text}) { return Padding( - padding: const EdgeInsets.all(20.0), - child: Text( - text, - style: const TextStyle(fontSize: 10.0, color: placeholderColor), - )); + padding: const EdgeInsets.symmetric(horizontal: 20.0, vertical: 10.0), + child: Text( + text, + style: const TextStyle(fontSize: 10.0, color: placeholderColor), + ), + ); } } diff --git a/lib/widgets/fields/dropdown_field.dart b/lib/widgets/fields/dropdown_field.dart index 1993dd1..ec0e538 100644 --- a/lib/widgets/fields/dropdown_field.dart +++ b/lib/widgets/fields/dropdown_field.dart @@ -1,6 +1,4 @@ import 'package:flutter/material.dart'; -import 'package:flutter/services.dart'; -import 'package:satu/shared/app_colors.dart'; import 'package:satu/shared/shared_styles.dart'; import 'package:satu/shared/ui_helpers.dart'; diff --git a/lib/widgets/fields/input_checkbox.dart b/lib/widgets/fields/input_checkbox.dart new file mode 100644 index 0000000..3c8b111 --- /dev/null +++ b/lib/widgets/fields/input_checkbox.dart @@ -0,0 +1,67 @@ +import 'package:flutter/material.dart'; +import 'package:satu/shared/app_colors.dart'; +import 'package:satu/shared/ui_helpers.dart'; + +import 'note_text.dart'; + +class InputCheckBox extends StatelessWidget { + const InputCheckBox(this.text, + {required this.value, this.labelText, this.onChanged}); + + final String text; + final bool value; + final String? labelText; + final Function(bool? value)? onChanged; + + Color getColor(Set states) { + const Set interactiveStates = { + MaterialState.pressed, + MaterialState.hovered, + MaterialState.focused, + }; + if (states.any(interactiveStates.contains)) { + return Colors.blue; + } + return primaryColor; + } + + @override + Widget build(BuildContext context) { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + if (labelText != null) + Padding( + padding: + const EdgeInsets.symmetric(horizontal: 14.0, vertical: 5.0), + child: NoteText(labelText ?? ''), + ), + Container( + decoration: const BoxDecoration(color: whiteColor), + child: Padding( + padding: EdgeInsets.only(left: 5, right: 15), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Checkbox( + value: value, + onChanged: onChanged, + //checkColor: primaryColor, + fillColor: MaterialStateProperty.resolveWith(getColor), + ), + Text( + text, + style: TextStyle( + fontSize: 12, + fontWeight: FontWeight.normal, + ), + ), + ], + ), + ), + ), + verticalSpaceSmall + ], + ); + } +} diff --git a/lib/widgets/fields/input_field.dart b/lib/widgets/fields/input_field.dart index 2b28713..7cb6160 100644 --- a/lib/widgets/fields/input_field.dart +++ b/lib/widgets/fields/input_field.dart @@ -8,25 +8,6 @@ import 'package:satu/shared/ui_helpers.dart'; import 'note_text.dart'; class InputField extends StatefulWidget { - final TextEditingController controller; - final TextInputType textInputType; - final bool password; - final bool search; - final bool isReadOnly; - final String? placeholder; - final String? validationMessage; - final Function? enterPressed; - final bool smallVersion; - final FocusNode? fieldFocusNode; - final FocusNode? nextFocusNode; - final TextInputAction textInputAction; - final bool multiline; - final String? additionalNote; - final Function(String)? onChanged; - final TextInputFormatter? formatter; - final String? initialValue; - final String? labelText; - final String? suffixText; InputField( {required this.controller, @@ -48,6 +29,25 @@ class InputField extends StatefulWidget { this.multiline = false, this.smallVersion = false, this.labelText}); + final TextEditingController controller; + final TextInputType textInputType; + final bool password; + final bool search; + final bool isReadOnly; + final String? placeholder; + final String? validationMessage; + final Function? enterPressed; + final bool smallVersion; + final FocusNode? fieldFocusNode; + final FocusNode? nextFocusNode; + final TextInputAction textInputAction; + final bool multiline; + final String? additionalNote; + final Function(String)? onChanged; + final TextInputFormatter? formatter; + final String? initialValue; + final String? labelText; + final String? suffixText; @override _InputFieldState createState() => _InputFieldState(); @@ -105,7 +105,7 @@ class _InputFieldState extends State { }); FocusScope.of(context) .requestFocus(FocusNode()); //remove focus - WidgetsBinding.instance!.addPostFrameCallback( + WidgetsBinding.instance.addPostFrameCallback( (_) => widget.controller.clear()); // clear content } }, diff --git a/lib/widgets/fields/input_field_rounded.dart b/lib/widgets/fields/input_field_rounded.dart index d0b050b..de035ab 100644 --- a/lib/widgets/fields/input_field_rounded.dart +++ b/lib/widgets/fields/input_field_rounded.dart @@ -8,6 +8,27 @@ import 'package:satu/shared/ui_helpers.dart'; import 'note_text.dart'; class InputFieldRounded extends StatefulWidget { + InputFieldRounded( + {required this.controller, + required this.placeholder, + this.enterPressed, + this.fieldFocusNode, + this.nextFocusNode, + this.additionalNote, + this.onChanged, + this.formatter, + this.suffixText, + this.initialValue, + this.validationMessage, + this.textInputAction = TextInputAction.next, + this.textInputType = TextInputType.text, + this.password = false, + this.search = false, + this.isReadOnly = false, + this.multiline = false, + this.smallVersion = false, + this.labelText}); + final TextEditingController controller; final TextInputType textInputType; final bool password; @@ -28,27 +49,6 @@ class InputFieldRounded extends StatefulWidget { final String? labelText; final String? suffixText; - InputFieldRounded( - {required this.controller, - required this.placeholder, - this.enterPressed, - this.fieldFocusNode, - this.nextFocusNode, - this.additionalNote, - this.onChanged, - this.formatter, - this.suffixText, - this.initialValue, - this.validationMessage, - this.textInputAction = TextInputAction.next, - this.textInputType = TextInputType.text, - this.password = false, - this.search = false, - this.isReadOnly = false, - this.multiline = false, - this.smallVersion = false, - this.labelText}); - @override _InputFieldRoundedState createState() => _InputFieldRoundedState(); } @@ -90,10 +90,12 @@ class _InputFieldRoundedState extends State { minHeight: widget.smallVersion ? 40.h : fieldHeight), alignment: Alignment.centerLeft, padding: fieldPadding, - decoration: - widget.isReadOnly ? disabledFieldDecoration : BoxDecoration( color: whiteColor , borderRadius: BorderRadius.circular(6.0), boxShadow: [ - inputShadowBox - ]), + decoration: widget.isReadOnly + ? disabledFieldDecoration + : BoxDecoration( + color: whiteColor, + borderRadius: BorderRadius.circular(6.0), + boxShadow: [inputShadowBox]), child: Row( children: [ GestureDetector( @@ -106,7 +108,7 @@ class _InputFieldRoundedState extends State { }); FocusScope.of(context) .requestFocus(new FocusNode()); //remove focus - WidgetsBinding.instance!.addPostFrameCallback( + WidgetsBinding.instance.addPostFrameCallback( (_) => widget.controller.clear()); // clear content } }, @@ -123,9 +125,7 @@ class _InputFieldRoundedState extends State { child: TextFormField( style: TextStyle( color: textColor, - fontSize: widget.smallVersion - ? 12 - : 14), + fontSize: widget.smallVersion ? 12 : 14), controller: widget.controller, keyboardType: widget.textInputType, focusNode: widget.fieldFocusNode, diff --git a/lib/widgets/fields/line_checkbox.dart b/lib/widgets/fields/line_checkbox.dart index 4427975..6623c4f 100644 --- a/lib/widgets/fields/line_checkbox.dart +++ b/lib/widgets/fields/line_checkbox.dart @@ -1,4 +1,3 @@ -import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:satu/shared/app_colors.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; diff --git a/lib/widgets/fields/note_text.dart b/lib/widgets/fields/note_text.dart index bf597ba..ab695fa 100644 --- a/lib/widgets/fields/note_text.dart +++ b/lib/widgets/fields/note_text.dart @@ -1,6 +1,5 @@ import 'package:flutter/material.dart'; import 'package:satu/shared/app_colors.dart'; -import 'package:flutter_screenutil/flutter_screenutil.dart'; class NoteText extends StatelessWidget { const NoteText(this.text, {this.textAlign, this.color, this.fontSize}); diff --git a/lib/widgets/tools/app_barcode_scanner_widget.dart b/lib/widgets/tools/app_barcode_scanner_widget.dart index 9165588..bc46e92 100644 --- a/lib/widgets/tools/app_barcode_scanner_widget.dart +++ b/lib/widgets/tools/app_barcode_scanner_widget.dart @@ -40,9 +40,7 @@ class _BarcodePermissionWidget extends StatefulWidget { class _BarcodePermissionWidgetState extends State<_BarcodePermissionWidget> { bool _isGranted = false; - bool _useCameraScan = true; - String _inputValue = ""; @override void initState() { diff --git a/lib/widgets/ui/product_title_widget.dart b/lib/widgets/ui/product_title_widget.dart index 74639e7..0ed812c 100644 --- a/lib/widgets/ui/product_title_widget.dart +++ b/lib/widgets/ui/product_title_widget.dart @@ -1,8 +1,6 @@ import 'package:flutter/material.dart'; -import 'package:flutter_screenutil/flutter_screenutil.dart'; import 'package:satu/shared/app_colors.dart'; import 'package:satu/shared/ui_helpers.dart'; -import 'package:satu/views/work/tabs/component/product_list_item.dart'; class ProductTitleWidget extends StatelessWidget { const ProductTitleWidget( diff --git a/pubspec.lock b/pubspec.lock index 22fe4fa..d831591 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -175,7 +175,7 @@ packages: name: collection url: "https://pub.dartlang.org" source: hosted - version: "1.15.0" + version: "1.16.0" convert: dependency: transitive description: @@ -252,7 +252,7 @@ packages: name: fake_async url: "https://pub.dartlang.org" source: hosted - version: "1.2.0" + version: "1.3.0" ffi: dependency: transitive description: @@ -286,13 +286,20 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "0.1.7" + flutter_lints: + dependency: "direct dev" + description: + name: flutter_lints + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.1" flutter_redux: dependency: "direct main" description: name: flutter_redux url: "https://pub.dartlang.org" source: hosted - version: "0.8.2" + version: "0.10.0" flutter_screenutil: dependency: "direct main" description: @@ -358,7 +365,7 @@ packages: name: grouped_list url: "https://pub.dartlang.org" source: hosted - version: "4.2.0" + version: "5.1.2" hex: dependency: transitive description: @@ -408,6 +415,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "0.4.2" + infinite_scroll_pagination: + dependency: "direct main" + description: + name: infinite_scroll_pagination + url: "https://pub.dartlang.org" + source: hosted + version: "3.2.0" intl: dependency: "direct main" description: @@ -428,7 +442,7 @@ packages: name: js url: "https://pub.dartlang.org" source: hosted - version: "0.6.3" + version: "0.6.4" json_annotation: dependency: transitive description: @@ -443,13 +457,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "6.2.0" - lint: - dependency: "direct dev" + lints: + dependency: transitive description: - name: lint + name: lints url: "https://pub.dartlang.org" source: hosted - version: "1.8.2" + version: "2.0.0" location_permissions: dependency: "direct main" description: @@ -491,7 +505,7 @@ packages: name: material_color_utilities url: "https://pub.dartlang.org" source: hosted - version: "0.1.3" + version: "0.1.4" material_design_icons_flutter: dependency: "direct main" description: @@ -540,7 +554,7 @@ packages: name: path url: "https://pub.dartlang.org" source: hosted - version: "1.8.0" + version: "1.8.1" path_drawing: dependency: transitive description: @@ -805,6 +819,13 @@ packages: description: flutter source: sdk version: "0.0.99" + sliver_tools: + dependency: transitive + description: + name: sliver_tools + url: "https://pub.dartlang.org" + source: hosted + version: "0.2.7" source_gen: dependency: transitive description: @@ -825,7 +846,7 @@ packages: name: source_span url: "https://pub.dartlang.org" source: hosted - version: "1.8.1" + version: "1.8.2" sqflite: dependency: "direct main" description: @@ -888,7 +909,7 @@ packages: name: test_api url: "https://pub.dartlang.org" source: hosted - version: "0.4.8" + version: "0.4.9" timing: dependency: transitive description: @@ -986,7 +1007,7 @@ packages: name: vector_math url: "https://pub.dartlang.org" source: hosted - version: "2.1.1" + version: "2.1.2" watcher: dependency: transitive description: @@ -1030,5 +1051,5 @@ packages: source: hosted version: "3.1.1" sdks: - dart: ">=2.16.0 <3.0.0" + dart: ">=2.17.3 <3.0.0" flutter: ">=2.10.0" diff --git a/pubspec.yaml b/pubspec.yaml index 8dd6efb..1b50567 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -17,15 +17,16 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html version: 1.0.0+1 + environment: - sdk: ">=2.14.0 <3.0.0" + sdk: ">=2.17.3 <3.0.0" dependencies: flutter: sdk: flutter cupertino_icons: ^1.0.5 redux: ^5.0.0 - flutter_redux: ^0.8.2 + flutter_redux: ^0.10.0 redux_thunk: ^0.4.0 redux_persist: ^0.9.0 redux_persist_flutter: ^0.9.0 @@ -53,7 +54,8 @@ dependencies: ai_barcode: ^3.2.0 permission_handler: ^8.3.0 flutter_svg: ^0.23.0+1 - grouped_list: ^4.2.0 + grouped_list: ^5.1.2 + infinite_scroll_pagination: ^3.2.0 flutter_bluetooth_basic: ^0.1.7 location_permissions: ^4.0.1 esc_pos_utils: ^1.1.0 @@ -62,9 +64,14 @@ dev_dependencies: build_runner: ^2.1.5 flutter_test: sdk: flutter - lint: ^1.7.2 json_serializable: ^6.0.1 + # The "flutter_lints" package below contains a set of recommended lints to + # encourage good coding practices. The lint set provided by the package is + # activated in the `analysis_options.yaml` file located at the root of your + # package. See that file for information about deactivating specific lint + # rules and activating additional ones. + flutter_lints: ^2.0.0 # For information on the generic Dart part of this file, see the # following page: https://dart.dev/tools/pub/pubspec