dictionaries
parent
44a6de4f58
commit
34b669eea0
17
README.md
17
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
|
||||
File diff suppressed because one or more lines are too long
|
After Width: | Height: | Size: 16 KiB |
|
|
@ -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',
|
||||
);
|
||||
}
|
||||
|
|
@ -1,4 +1,3 @@
|
|||
import 'package:flutter/foundation.dart';
|
||||
|
||||
class DialogRequest {
|
||||
DialogRequest(
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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<String, dynamic> 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<String, dynamic> toJson() => _$ContragentResponseEntityToJson(this);
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return jsonEncode(this);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
|
||||
part of 'contragent_response_entity.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// JsonSerializableGenerator
|
||||
// **************************************************************************
|
||||
|
||||
ContragentResponseEntity _$ContragentResponseEntityFromJson(
|
||||
Map<String, dynamic> 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<String, dynamic> _$ContragentResponseEntityToJson(
|
||||
ContragentResponseEntity instance) =>
|
||||
<String, dynamic>{
|
||||
'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,
|
||||
};
|
||||
|
|
@ -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<num>(map['price']) ?? 0).toDouble() ;
|
||||
goodResponseBean.optPrice = (cast<num>(map['opt_price']) ?? 0).toDouble();
|
||||
goodResponseBean.basePrice = (cast<num>(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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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<String, dynamic> json) => _$DictResponseEntityFromJson(json);
|
||||
|
||||
DictResponseEntity();
|
||||
|
||||
late DictResponseHeaders headers;
|
||||
late DictResponseOriginal original;
|
||||
String? exception;
|
||||
|
||||
Map<String, dynamic> toJson() => _$DictResponseEntityToJson(this);
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return jsonEncode(this);
|
||||
}
|
||||
}
|
||||
|
||||
@JsonSerializable()
|
||||
class DictResponseHeaders {
|
||||
|
||||
|
||||
|
||||
DictResponseHeaders();
|
||||
|
||||
factory DictResponseHeaders.fromJson(Map<String, dynamic> json) => _$DictResponseHeadersFromJson(json);
|
||||
|
||||
Map<String, dynamic> toJson() => _$DictResponseHeadersToJson(this);
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return jsonEncode(this);
|
||||
}
|
||||
}
|
||||
|
||||
@JsonSerializable()
|
||||
class DictResponseOriginal {
|
||||
|
||||
factory DictResponseOriginal.fromJson(Map<String, dynamic> json) => _$DictResponseOriginalFromJson(json);
|
||||
|
||||
DictResponseOriginal();
|
||||
|
||||
int? overall;
|
||||
int? page;
|
||||
int? perpage;
|
||||
List<dynamic>? data;
|
||||
Map<String, List<String>>? errors;
|
||||
String? message;
|
||||
|
||||
Map<String, dynamic> toJson() => _$DictResponseOriginalToJson(this);
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return jsonEncode(this);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,53 @@
|
|||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
|
||||
part of 'dict_response_entity.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// JsonSerializableGenerator
|
||||
// **************************************************************************
|
||||
|
||||
DictResponseEntity _$DictResponseEntityFromJson(Map<String, dynamic> json) =>
|
||||
DictResponseEntity()
|
||||
..headers =
|
||||
DictResponseHeaders.fromJson(json['headers'] as Map<String, dynamic>)
|
||||
..original = DictResponseOriginal.fromJson(
|
||||
json['original'] as Map<String, dynamic>)
|
||||
..exception = json['exception'] as String?;
|
||||
|
||||
Map<String, dynamic> _$DictResponseEntityToJson(DictResponseEntity instance) =>
|
||||
<String, dynamic>{
|
||||
'headers': instance.headers,
|
||||
'original': instance.original,
|
||||
'exception': instance.exception,
|
||||
};
|
||||
|
||||
DictResponseHeaders _$DictResponseHeadersFromJson(Map<String, dynamic> json) =>
|
||||
DictResponseHeaders();
|
||||
|
||||
Map<String, dynamic> _$DictResponseHeadersToJson(
|
||||
DictResponseHeaders instance) =>
|
||||
<String, dynamic>{};
|
||||
|
||||
DictResponseOriginal _$DictResponseOriginalFromJson(
|
||||
Map<String, dynamic> json) =>
|
||||
DictResponseOriginal()
|
||||
..overall = json['overall'] as int?
|
||||
..page = json['page'] as int?
|
||||
..perpage = json['perpage'] as int?
|
||||
..data = json['data'] as List<dynamic>?
|
||||
..errors = (json['errors'] as Map<String, dynamic>?)?.map(
|
||||
(k, e) =>
|
||||
MapEntry(k, (e as List<dynamic>).map((e) => e as String).toList()),
|
||||
)
|
||||
..message = json['message'] as String?;
|
||||
|
||||
Map<String, dynamic> _$DictResponseOriginalToJson(
|
||||
DictResponseOriginal instance) =>
|
||||
<String, dynamic>{
|
||||
'overall': instance.overall,
|
||||
'page': instance.page,
|
||||
'perpage': instance.perpage,
|
||||
'data': instance.data,
|
||||
'errors': instance.errors,
|
||||
'message': instance.message,
|
||||
};
|
||||
|
|
@ -1,4 +1,3 @@
|
|||
import 'package:satu/core/utils/utils_parse.dart';
|
||||
|
||||
class TransactionDao {
|
||||
TransactionDao();
|
||||
|
|
|
|||
|
|
@ -4,13 +4,13 @@ part 'sell_return_request.g.dart';
|
|||
|
||||
@JsonSerializable()
|
||||
class SellReturnRequest {
|
||||
int journal_id;
|
||||
String invoice_id;
|
||||
factory SellReturnRequest.fromJson(Map<String, dynamic> json) =>
|
||||
_$SellReturnRequestFromJson(json);
|
||||
|
||||
SellReturnRequest({required this.journal_id, required this.invoice_id});
|
||||
|
||||
factory SellReturnRequest.fromJson(Map<String, dynamic> json) => _$SellReturnRequestFromJson(json);
|
||||
int journal_id;
|
||||
String invoice_id;
|
||||
|
||||
Map<String, dynamic> toJson() => _$SellReturnRequestToJson(this);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -6,12 +6,11 @@ part of 'sell_return_request.dart';
|
|||
// JsonSerializableGenerator
|
||||
// **************************************************************************
|
||||
|
||||
SellReturnRequest _$SellReturnRequestFromJson(Map<String, dynamic> json) {
|
||||
return SellReturnRequest(
|
||||
journal_id: json['journal_id'] as int,
|
||||
invoice_id: json['invoice_id'] as String,
|
||||
);
|
||||
}
|
||||
SellReturnRequest _$SellReturnRequestFromJson(Map<String, dynamic> json) =>
|
||||
SellReturnRequest(
|
||||
journal_id: json['journal_id'] as int,
|
||||
invoice_id: json['invoice_id'] as String,
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$SellReturnRequestToJson(SellReturnRequest instance) =>
|
||||
<String, dynamic>{
|
||||
|
|
|
|||
|
|
@ -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<String>(map['message']);
|
||||
responseBean.operation = map['operation'] as bool;
|
||||
return responseBean;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -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<String>(map['encoding']),
|
||||
paperSize: cast<String>(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<String>(map['encoding']),
|
||||
paperSize: cast<String>(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<bool>(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,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
@ -1,4 +1,3 @@
|
|||
import 'package:satu/core/utils/utils_parse.dart';
|
||||
|
||||
class PopupItemDao {
|
||||
PopupItemDao({required this.code, required this.name});
|
||||
|
|
|
|||
|
|
@ -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<void> loadJournalData(Store<AppState> store) async {
|
|||
try {
|
||||
log.i('loadJournalData');
|
||||
final int? appCompanyId = store.state.userState!.auth!.companyId;
|
||||
final int tabIndex = store.state.journalState?.tabIndex ?? 0;
|
||||
final List<Map<String, dynamic>> set = await _dbService.queryRowsWithWhere(
|
||||
transactionTableName,
|
||||
'$transactionColumnAppCompanyId = ?'
|
||||
|
|
@ -75,7 +67,7 @@ Future<void> loadJournalData(Store<AppState> 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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -8,8 +8,8 @@ import '../store.dart';
|
|||
|
||||
@immutable
|
||||
class SetNavStateAction {
|
||||
final NavState navState;
|
||||
SetNavStateAction(this.navState);
|
||||
final NavState navState;
|
||||
}
|
||||
|
||||
ThunkAction<AppState> navigateDrawer(Type viewClass) {
|
||||
|
|
|
|||
|
|
@ -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';
|
||||
|
||||
|
|
|
|||
|
|
@ -13,9 +13,9 @@ import '../store.dart';
|
|||
|
||||
@immutable
|
||||
class SetUserStateAction {
|
||||
final UserState userState;
|
||||
|
||||
SetUserStateAction(this.userState);
|
||||
final UserState userState;
|
||||
}
|
||||
|
||||
final ApiService _api = locator<ApiService>();
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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<ProductDao>? items;
|
||||
final TransactionState? transactionState;
|
||||
|
||||
SellState({this.items, this.transactionState});
|
||||
|
||||
factory SellState.initial() => SellState(
|
||||
items: [],
|
||||
transactionState: TransactionState(),
|
||||
);
|
||||
|
||||
SellState copyWith({required List<ProductDao>? items, required TransactionState? transactionState}) {
|
||||
return SellState(items: items ?? this.items, transactionState: transactionState ?? this.transactionState);
|
||||
SellState({this.items, this.transactionState});
|
||||
|
||||
final List<ProductDao>? items;
|
||||
final TransactionState? transactionState;
|
||||
|
||||
SellState copyWith(
|
||||
{required List<ProductDao>? items,
|
||||
required TransactionState? transactionState}) {
|
||||
return SellState(
|
||||
items: items ?? this.items,
|
||||
transactionState: transactionState ?? this.transactionState);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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<AppState>(
|
||||
appReducer,
|
||||
|
|
|
|||
|
|
@ -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<String, dynamic>? requestBody, Map<String, String>? header}) async {
|
||||
final Map<String, String> headers = <String, String>{
|
||||
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<Response> dictionaries(String target) async {
|
||||
Response result;
|
||||
Future<DictResponseEntity> dictionaries(String target,
|
||||
{Map<String, dynamic>? requestBody}) async {
|
||||
DictResponseEntity result;
|
||||
try {
|
||||
final Map<String, String> headers = <String, String>{
|
||||
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<DictResponseEntity> dictionarySave(
|
||||
String target, Map<String, dynamic>? body) async {
|
||||
DictResponseEntity response;
|
||||
try {
|
||||
final Map<String, String> headers = <String, String>{
|
||||
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<SellResponse> sell(SellRequest request) async {
|
||||
SellResponse response;
|
||||
try {
|
||||
final Map<String, String> headers = <String, String>{
|
||||
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<String, String> headers = <String, String>{
|
||||
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);
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
||||
|
|
|
|||
|
|
@ -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<DialogResponse> showDialog({
|
||||
String title = 'SATU',
|
||||
String? description,
|
||||
|
|
|
|||
|
|
@ -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<DbService>();
|
||||
|
||||
Future<void> refreshFull() async {
|
||||
_db.deleteAll(categoryTableName);
|
||||
await refreshCategory();
|
||||
_db.deleteAll(goodTableName);
|
||||
await refreshGood();
|
||||
|
||||
}
|
||||
|
||||
Future<void> 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<List<Category>> getCategoryByParentId(int parentId) async {
|
||||
final List<Category> list = [];
|
||||
|
|
@ -77,23 +56,7 @@ class DictionaryService extends BaseService {
|
|||
return result;
|
||||
}
|
||||
|
||||
Future<List<Category>> getCategoriesAll() async {
|
||||
final List<Category> list = [];
|
||||
try {
|
||||
final int? appCompanyId = Redux.store?.state.userState?.auth?.companyId;
|
||||
final List<Map<String, dynamic>> elements = await _db.queryRowsWithWhere(
|
||||
categoryTableName,
|
||||
'$categoryColumnAppCompanyId = ? '
|
||||
' order by $categoryColumnParentIn asc, $categoryColumnId asc ',
|
||||
[appCompanyId]);
|
||||
for (final Map<String, dynamic> element in elements) {
|
||||
list.add(Category.fromMap(element));
|
||||
}
|
||||
} catch (e, stack) {
|
||||
log.e('getCategoriesAll', e, stack);
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
|
||||
Future<List<Good>> getGoodsByCategoryId(int categoryId) async {
|
||||
final List<Good> list = [];
|
||||
|
|
@ -134,55 +97,126 @@ class DictionaryService extends BaseService {
|
|||
return list;
|
||||
}
|
||||
|
||||
Future<List<Good>> getGoodsByEan(String code) async {
|
||||
final List<Good> 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<Map<String, dynamic>> elements =
|
||||
await _db.queryRowsWithWhere(goodTableName, where, args);
|
||||
for (final Map<String, dynamic> 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<void> refreshGood() async {
|
||||
Future<List<CategoryResponse>> getCategories( {required int page, String? query, required int perpage}) async {
|
||||
List<CategoryResponse> 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<String, dynamic> requestBody = <String, dynamic>{
|
||||
'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<List<GoodResponse>> getGoods(
|
||||
{required int page, String? query, required int perpage}) async {
|
||||
List<GoodResponse> list = [];
|
||||
try {
|
||||
final Map<String, dynamic> requestBody = <String, dynamic>{
|
||||
'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<List<ContragentResponseEntity>> getContragents(
|
||||
{int? page, int? perpage, String? query}) async {
|
||||
final List<ContragentResponseEntity> list = [];
|
||||
try {
|
||||
final Map<String, dynamic> requestBody = <String, dynamic>{
|
||||
'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<String?> 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<String?> 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<String, List<String>> errors = status.original.errors!;
|
||||
errors.values.forEach((element) {
|
||||
message = '${message ?? ''} \n ${element.join(',')}';
|
||||
});
|
||||
}
|
||||
return message;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,11 +14,11 @@ class NavigatorService extends BaseService {
|
|||
|
||||
Future<dynamic> replace(String routeName, {dynamic arguments}) {
|
||||
log.d('routeName: $routeName');
|
||||
return navigatorKey.currentState!
|
||||
.pushNamedAndRemoveUntil(routeName, (Route<dynamic> route) => false, arguments: arguments);
|
||||
return navigatorKey.currentState!.pushNamedAndRemoveUntil(
|
||||
routeName, (Route<dynamic> route) => false,
|
||||
arguments: arguments);
|
||||
}
|
||||
|
||||
|
||||
Future<T?> navigateToPage<T>(MaterialPageRoute<T> pageRoute) async {
|
||||
log.d('navigateToPage: pageRoute: ${pageRoute.settings.name}');
|
||||
if (navigatorKey.currentState == null) {
|
||||
|
|
@ -31,7 +31,7 @@ class NavigatorService extends BaseService {
|
|||
Future<T?> navigateToPageWithReplacement<T>(
|
||||
MaterialPageRoute<T> 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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<String> log(LogEvent event) {
|
||||
|
|
|
|||
|
|
@ -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';
|
||||
|
|
|
|||
|
|
@ -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<dynamic> 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<dynamic> 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(
|
||||
|
|
|
|||
|
|
@ -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<CategoryEdit> {
|
|||
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<CategoryEdit> {
|
|||
super.dispose();
|
||||
}
|
||||
|
||||
Future<void> 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<CategoryEdit> {
|
|||
children: [
|
||||
verticalSpaceSmall,
|
||||
LineTile(
|
||||
parentCategoryName,
|
||||
parentCategoryName ?? 'Корневая категория',
|
||||
onTap: selectCategory,
|
||||
labelText: 'Родительская категория',
|
||||
),
|
||||
|
|
@ -133,8 +114,11 @@ class _CategoryEditState extends State<CategoryEdit> {
|
|||
Future<void> 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;
|
||||
});
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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<CategorySelectView> {
|
|||
late TextEditingController _searchTextController;
|
||||
final FocusNode _searchFocusNode = FocusNode();
|
||||
|
||||
late List<Category> _categories = [];
|
||||
|
||||
late List<CategoryRowDao> items = [];
|
||||
static const _pageSize = 20;
|
||||
String query = '';
|
||||
Timer? _debounce;
|
||||
final PagingController<int, CategoryResponse> _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<void> initQuery() async {
|
||||
_categories = await _dictionaryService.getCategoriesAll();
|
||||
searchByField('');
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_debounce?.cancel();
|
||||
_pagingController.dispose();
|
||||
_searchTextController.dispose();
|
||||
_searchFocusNode.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
Future<void> handlerCategory(int id) async {
|
||||
_navigatorService.pop(id);
|
||||
Future<void> handlerCategory(CategoryResponse? category) async {
|
||||
_navigatorService.pop(category);
|
||||
}
|
||||
|
||||
@override
|
||||
|
|
@ -82,43 +83,47 @@ class _CategorySelectViewState extends State<CategorySelectView> {
|
|||
'Корневая категория',
|
||||
value: true,
|
||||
labelText: 'По умолчанию',
|
||||
onTap: () => handlerCategory(0),
|
||||
onTap: () => handlerCategory(null),
|
||||
),
|
||||
const ProductsTitleBarBar(title: 'Выберите категорию'),
|
||||
Expanded(
|
||||
child: ListView.separated(
|
||||
child: PagedListView<int, CategoryResponse>.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<CategoryResponse>(
|
||||
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<CategorySelectView> {
|
|||
|
||||
void reset() {
|
||||
_searchTextController.clear();
|
||||
searchByField('');
|
||||
}
|
||||
|
||||
void searchByField(String query) async {
|
||||
final List<CategoryRowDao> list = [];
|
||||
final Iterable<Category> 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<void> _fetchData(int pageKey, int perPage, String? query) async {
|
||||
final List<CategoryResponse> 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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<CategoryDictionaryView> {
|
|||
late TextEditingController _searchTextController;
|
||||
final FocusNode _searchFocusNode = new FocusNode();
|
||||
|
||||
late List<Category> _categories = [];
|
||||
|
||||
late List<CategoryRowDao> items = [];
|
||||
static const _pageSize = 20;
|
||||
String query = '';
|
||||
Timer? _debounce;
|
||||
|
||||
final PagingController<int, CategoryResponse> _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<void> 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<CategoryDictionaryView> {
|
|||
),
|
||||
const ProductsTitleBarBar(title: 'Список категории'),
|
||||
Expanded(
|
||||
child: ListView.separated(
|
||||
child: PagedListView<int, CategoryResponse>.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<CategoryResponse>(
|
||||
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<CategoryDictionaryView> {
|
|||
|
||||
void reset() {
|
||||
_searchTextController.clear();
|
||||
searchByField('');
|
||||
}
|
||||
|
||||
void searchByField(String query) async {
|
||||
log.i(query);
|
||||
final List<CategoryRowDao> list = [];
|
||||
final Iterable<Category> 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<void> _fetchData(int pageKey, int perPage, String? query) async {
|
||||
final List<CategoryResponse> 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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<ContragentEdit> {
|
||||
final NavigatorService _navigatorService = locator<NavigatorService>();
|
||||
final DictionaryService _dictionaryService = locator<DictionaryService>();
|
||||
final DialogService _dialogService = locator<DialogService>();
|
||||
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,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -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<ContragentsDictionaryView> {
|
||||
final DictionaryService _dictionaryService = locator<DictionaryService>();
|
||||
final NavigatorService _navigatorService = locator<NavigatorService>();
|
||||
late TextEditingController _searchTextController;
|
||||
final FocusNode _searchFocusNode = FocusNode();
|
||||
|
||||
late List<ContragentResponseEntity> items = [];
|
||||
static const _pageSize = 20;
|
||||
|
||||
final PagingController<int, ContragentResponseEntity> _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<void> 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<int, ContragentResponseEntity>(
|
||||
pagingController: _pagingController,
|
||||
builderDelegate:
|
||||
PagedChildBuilderDelegate<ContragentResponseEntity>(
|
||||
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<NavigatorService>().push(contragentEditRoute,
|
||||
arguments: ContragentResponseEntity()..refAppCompanyTypeId = 5),
|
||||
child: const Icon(
|
||||
Icons.add_rounded,
|
||||
size: 34.0,
|
||||
color: whiteColor,
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
void reset() {
|
||||
_searchTextController.clear();
|
||||
}
|
||||
|
||||
Future<void> _fetchData(int pageKey, int perPage, String? query) async {
|
||||
final List<ContragentResponseEntity> 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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<GoodEdit> {
|
|||
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<GoodEdit> {
|
|||
super.dispose();
|
||||
}
|
||||
|
||||
Future<void> 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<void> 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<GoodEdit> {
|
|||
final dynamic result =
|
||||
await _navigatorService.push(categorySelectViewRoute);
|
||||
if (result != null) {
|
||||
getAndStateCategoryName(result as int);
|
||||
//getAndStateCategoryName(result as int);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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<GoodsDictionaryView> {
|
|||
final NavigatorService _navigatorService = locator<NavigatorService>();
|
||||
late TextEditingController _searchTextController;
|
||||
final FocusNode _searchFocusNode = FocusNode();
|
||||
static const _pageSize = 20;
|
||||
String query = '';
|
||||
Timer? _debounce;
|
||||
|
||||
late List<Good> _goods = [];
|
||||
late List<Category> _categories = [];
|
||||
late List<GoodRowDao> items = [];
|
||||
final PagingController<int, GoodResponse> _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<void> 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<GoodsDictionaryView> {
|
|||
),
|
||||
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<NavigatorService>()
|
||||
.push(goodsEditRoute, arguments: good);
|
||||
child: PagedListView<int, GoodResponse>.separated(
|
||||
physics: const BouncingScrollPhysics(),
|
||||
separatorBuilder: (BuildContext context, int index) {
|
||||
return const Divider(
|
||||
height: 1.0,
|
||||
color: disableColor,
|
||||
);
|
||||
},
|
||||
pagingController: _pagingController,
|
||||
builderDelegate: PagedChildBuilderDelegate<GoodResponse>(
|
||||
itemBuilder:
|
||||
(BuildContext context, GoodResponse good, int index) {
|
||||
return DictionaryTile(
|
||||
onPress: () {
|
||||
locator<NavigatorService>()
|
||||
.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<NavigatorService>()
|
||||
.push(goodsEditRoute, arguments: GoodRowDao('', '')),
|
||||
onPressed: () =>
|
||||
locator<NavigatorService>()
|
||||
.push(goodsEditRoute, arguments: GoodRowDao('', '')),
|
||||
child: const Icon(
|
||||
Icons.add_rounded,
|
||||
size: 34.0,
|
||||
|
|
@ -136,30 +145,18 @@ class _GoodsDictionaryViewState extends State<GoodsDictionaryView> {
|
|||
|
||||
void reset() {
|
||||
_searchTextController.clear();
|
||||
searchByField('');
|
||||
}
|
||||
|
||||
Future<void> searchByField(String query) async {
|
||||
log.i(query);
|
||||
final List<GoodRowDao> list = [];
|
||||
final Iterable<Good> 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<void> _fetchData(int pageKey, int perPage, String? query) async {
|
||||
final List<GoodResponse> 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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<LoginView> {
|
|||
return StoreConnector<AppState, UserState>(
|
||||
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: <Widget>[
|
||||
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: <Widget>[
|
||||
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<LoginView> {
|
|||
_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});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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<MainView> {
|
|||
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<MainView> {
|
|||
if(viewClass == GoodsDictionaryView) {
|
||||
return _goodDictView;
|
||||
}
|
||||
if(viewClass == ContragentsDictionaryView) {
|
||||
return _contragentDictView;
|
||||
}
|
||||
if(viewClass == AnalyticsView) {
|
||||
return _analyticsView;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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';
|
||||
|
|
|
|||
|
|
@ -1,4 +1,3 @@
|
|||
import 'dart:io';
|
||||
|
||||
import 'package:esc_pos_bluetooth/esc_pos_bluetooth.dart';
|
||||
import 'package:flutter/material.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';
|
||||
|
||||
|
|
|
|||
|
|
@ -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<StartUpView> {
|
||||
final NavigatorService _navigation = locator<NavigatorService>();
|
||||
final ApiService _api = locator<ApiService>();
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
|
|
|
|||
|
|
@ -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';
|
||||
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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(
|
||||
|
|
|
|||
|
|
@ -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'))
|
||||
],
|
||||
),
|
||||
],
|
||||
|
|
|
|||
|
|
@ -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(
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
),
|
||||
),
|
||||
]),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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<Good> goods =
|
||||
await locator<DictionaryService>()
|
||||
.getGoodsByEan(result as String);
|
||||
if (goods.isNotEmpty) {
|
||||
Redux.store
|
||||
?.dispatch(addSellItem(good: goods.first));
|
||||
}
|
||||
// final List<Good> goods =
|
||||
// await locator<DictionaryService>()
|
||||
// .getGoodsByEan(result as String);
|
||||
// if (goods.isNotEmpty) {
|
||||
// Redux.store
|
||||
// ?.dispatch(addSellItem(good: goods.first));
|
||||
// }
|
||||
}
|
||||
},
|
||||
child: Icon(Icons.qr_code_rounded,
|
||||
|
|
|
|||
|
|
@ -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';
|
||||
|
|
|
|||
|
|
@ -26,25 +26,21 @@ class _AddProductViewState extends State<AddProductView> {
|
|||
late TextEditingController _searchTextController;
|
||||
final FocusNode _searchFocusNode = new FocusNode();
|
||||
|
||||
|
||||
List<Category>? _history;
|
||||
List<Category>? _categories;
|
||||
List<Good>? _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<AddProductView> {
|
|||
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<AddProductView> {
|
|||
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<AddProductView> {
|
|||
}
|
||||
|
||||
void reset() {
|
||||
_history = [Category()
|
||||
..id = 0
|
||||
];
|
||||
navigateCategory(0);
|
||||
_searchTextController.clear();
|
||||
}
|
||||
_history = [Category()..id = 0];
|
||||
navigateCategory(0);
|
||||
_searchTextController.clear();
|
||||
}
|
||||
|
||||
void navigateCategory(int categoryId) async {
|
||||
List<Category> categories = await _dictionaryService.getCategoryByParentId(categoryId);
|
||||
List<Good> goods = await _dictionaryService.getGoodsByCategoryId(categoryId);
|
||||
List<Category> categories =
|
||||
await _dictionaryService.getCategoryByParentId(categoryId);
|
||||
List<Good> goods =
|
||||
await _dictionaryService.getGoodsByCategoryId(categoryId);
|
||||
setState(() {
|
||||
_categories = categories;
|
||||
_goods = goods;
|
||||
|
|
@ -142,5 +147,4 @@ class _AddProductViewState extends State<AddProductView> {
|
|||
_goods = goods;
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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';
|
||||
|
|
|
|||
|
|
@ -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})
|
||||
|
|
|
|||
|
|
@ -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';
|
||||
|
|
|
|||
|
|
@ -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({
|
||||
|
|
|
|||
|
|
@ -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';
|
||||
|
|
|
|||
|
|
@ -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';
|
||||
|
|
|
|||
|
|
@ -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';
|
||||
|
|
|
|||
|
|
@ -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<Widget>? 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<Widget>? actions;
|
||||
final Widget? child;
|
||||
final double childHeight;
|
||||
final double elevation;
|
||||
final Color? backgroundColor;
|
||||
final bool drawerShow;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
|
|
|
|||
|
|
@ -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})
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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<DialogModalSelect> {
|
|||
radius: avatarRadius,
|
||||
child: ClipRRect(
|
||||
borderRadius: BorderRadius.all(Radius.circular(avatarRadius)),
|
||||
child: Image.asset("assets/model.jpeg")),
|
||||
child: Image.asset('assets/model.jpeg')),
|
||||
),
|
||||
)
|
||||
],
|
||||
|
|
|
|||
|
|
@ -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: <Widget>[
|
||||
margin: EdgeInsets.zero,
|
||||
padding: EdgeInsets.zero,
|
||||
decoration: const BoxDecoration(
|
||||
image: DecorationImage(
|
||||
fit: BoxFit.cover,
|
||||
image: AssetImage('assets/images/drawer/background.png'),
|
||||
),
|
||||
),
|
||||
child: Stack(
|
||||
children: <Widget>[
|
||||
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<AppState, UserState>(
|
||||
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<AppState, UserState>(
|
||||
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),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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';
|
||||
|
||||
|
|
|
|||
|
|
@ -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<MaterialState> states) {
|
||||
const Set<MaterialState> interactiveStates = <MaterialState>{
|
||||
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
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -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<InputField> {
|
|||
});
|
||||
FocusScope.of(context)
|
||||
.requestFocus(FocusNode()); //remove focus
|
||||
WidgetsBinding.instance!.addPostFrameCallback(
|
||||
WidgetsBinding.instance.addPostFrameCallback(
|
||||
(_) => widget.controller.clear()); // clear content
|
||||
}
|
||||
},
|
||||
|
|
|
|||
|
|
@ -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<InputFieldRounded> {
|
|||
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: <Widget>[
|
||||
GestureDetector(
|
||||
|
|
@ -106,7 +108,7 @@ class _InputFieldRoundedState extends State<InputFieldRounded> {
|
|||
});
|
||||
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<InputFieldRounded> {
|
|||
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,
|
||||
|
|
|
|||
|
|
@ -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';
|
||||
|
|
|
|||
|
|
@ -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});
|
||||
|
|
|
|||
|
|
@ -40,9 +40,7 @@ class _BarcodePermissionWidget extends StatefulWidget {
|
|||
class _BarcodePermissionWidgetState extends State<_BarcodePermissionWidget> {
|
||||
bool _isGranted = false;
|
||||
|
||||
bool _useCameraScan = true;
|
||||
|
||||
String _inputValue = "";
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
|
|
|
|||
|
|
@ -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(
|
||||
|
|
|
|||
51
pubspec.lock
51
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"
|
||||
|
|
|
|||
15
pubspec.yaml
15
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
|
||||
|
|
|
|||
Loading…
Reference in New Issue