dictionaries
parent
44a6de4f58
commit
34b669eea0
17
README.md
17
README.md
|
|
@ -1,19 +1,16 @@
|
||||||
# satu
|
# satu
|
||||||
|
|
||||||
Aman Satu App
|
Aman Satu App
|
||||||
|
|
||||||
## Getting Started
|
## 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:
|
# build android apk
|
||||||
|
flutter build --release apk --flavor production
|
||||||
- [Lab: Write your first Flutter app](https://flutter.dev/docs/get-started/codelab)
|
# build android appbundle
|
||||||
- [Cookbook: Useful Flutter samples](https://flutter.dev/docs/cookbook)
|
flutter build --release appbundle --flavor production
|
||||||
|
|
||||||
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.
|
|
||||||
|
|
||||||
## Сборка релизного пакет
|
## Сборка релизного пакет
|
||||||
flutter clean && flutter build appbundle --release
|
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';
|
import '../utils/logger.dart';
|
||||||
|
|
||||||
class BaseService {
|
class BaseService {
|
||||||
Logger log = getLogger(
|
|
||||||
'BaseService',
|
|
||||||
);
|
|
||||||
|
|
||||||
BaseService({String? title}) {
|
BaseService({String? title}) {
|
||||||
this.log = getLogger(
|
this.log = getLogger(
|
||||||
title ?? this.runtimeType.toString(),
|
title ?? this.runtimeType.toString(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
Logger log = getLogger(
|
||||||
|
'BaseService',
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
@ -1,4 +1,3 @@
|
||||||
import 'package:flutter/foundation.dart';
|
|
||||||
|
|
||||||
class DialogRequest {
|
class DialogRequest {
|
||||||
DialogRequest(
|
DialogRequest(
|
||||||
|
|
|
||||||
|
|
@ -9,11 +9,10 @@ class CategoryResponse {
|
||||||
String name = '';
|
String name = '';
|
||||||
String? updatedAt;
|
String? updatedAt;
|
||||||
|
|
||||||
static CategoryResponse? fromMap(dynamic map) {
|
static CategoryResponse fromMap(dynamic map) {
|
||||||
if (map == null) return null;
|
|
||||||
final CategoryResponse categoryResponseBean = CategoryResponse();
|
final CategoryResponse categoryResponseBean = CategoryResponse();
|
||||||
categoryResponseBean.id = map['id'] as int;
|
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.name = map['name'] as String;
|
||||||
categoryResponseBean.updatedAt = map['updated_at'] as String;
|
categoryResponseBean.updatedAt = map['updated_at'] as String;
|
||||||
return categoryResponseBean;
|
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;
|
double? basePrice;
|
||||||
int? divisible;
|
int? divisible;
|
||||||
String? updatedAt;
|
String? updatedAt;
|
||||||
|
String? categoryName;
|
||||||
|
|
||||||
|
|
||||||
static GoodResponse fromMap(dynamic map) {
|
static GoodResponse fromMap(dynamic map) {
|
||||||
final GoodResponse goodResponseBean = GoodResponse();
|
final GoodResponse goodResponseBean = GoodResponse();
|
||||||
goodResponseBean.id = map['id'] as int;
|
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.name = map['name'] as String;
|
||||||
goodResponseBean.ean = map['ean'] as String;
|
goodResponseBean.ean = map['ean'] as String?;
|
||||||
goodResponseBean.articul = map['articul'] as int;
|
goodResponseBean.articul = map['articul'] as int;
|
||||||
goodResponseBean.price = (cast<num>(map['price']) ?? 0).toDouble() ;
|
goodResponseBean.price = (cast<num>(map['price']) ?? 0).toDouble() ;
|
||||||
goodResponseBean.optPrice = (cast<num>(map['opt_price']) ?? 0).toDouble();
|
goodResponseBean.optPrice = (cast<num>(map['opt_price']) ?? 0).toDouble();
|
||||||
goodResponseBean.basePrice = (cast<num>(map['base_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.updatedAt = map['updated_at'] as String;
|
||||||
|
goodResponseBean.categoryName = map['category_name'] as String?;
|
||||||
return goodResponseBean;
|
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 {
|
class TransactionDao {
|
||||||
TransactionDao();
|
TransactionDao();
|
||||||
|
|
|
||||||
|
|
@ -4,13 +4,13 @@ part 'sell_return_request.g.dart';
|
||||||
|
|
||||||
@JsonSerializable()
|
@JsonSerializable()
|
||||||
class SellReturnRequest {
|
class SellReturnRequest {
|
||||||
int journal_id;
|
factory SellReturnRequest.fromJson(Map<String, dynamic> json) =>
|
||||||
String invoice_id;
|
_$SellReturnRequestFromJson(json);
|
||||||
|
|
||||||
SellReturnRequest({required this.journal_id, required this.invoice_id});
|
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);
|
Map<String, dynamic> toJson() => _$SellReturnRequestToJson(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -6,12 +6,11 @@ part of 'sell_return_request.dart';
|
||||||
// JsonSerializableGenerator
|
// JsonSerializableGenerator
|
||||||
// **************************************************************************
|
// **************************************************************************
|
||||||
|
|
||||||
SellReturnRequest _$SellReturnRequestFromJson(Map<String, dynamic> json) {
|
SellReturnRequest _$SellReturnRequestFromJson(Map<String, dynamic> json) =>
|
||||||
return SellReturnRequest(
|
SellReturnRequest(
|
||||||
journal_id: json['journal_id'] as int,
|
journal_id: json['journal_id'] as int,
|
||||||
invoice_id: json['invoice_id'] as String,
|
invoice_id: json['invoice_id'] as String,
|
||||||
);
|
);
|
||||||
}
|
|
||||||
|
|
||||||
Map<String, dynamic> _$SellReturnRequestToJson(SellReturnRequest instance) =>
|
Map<String, dynamic> _$SellReturnRequestToJson(SellReturnRequest instance) =>
|
||||||
<String, dynamic>{
|
<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 {
|
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({
|
PrinterSetting({
|
||||||
this.device,
|
this.device,
|
||||||
this.encoding = PrinterConst.encodingCP866,
|
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 {
|
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) {
|
factory PrinterDevice.fromMap(dynamic map) {
|
||||||
return PrinterDevice(
|
return PrinterDevice(
|
||||||
|
|
@ -70,4 +50,24 @@ class PrinterDevice {
|
||||||
connected: cast<bool>(map['connected']),
|
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 {
|
class PopupItemDao {
|
||||||
PopupItemDao({required this.code, required this.name});
|
PopupItemDao({required this.code, required this.name});
|
||||||
|
|
|
||||||
|
|
@ -5,20 +5,13 @@ import 'package:logger/logger.dart';
|
||||||
import 'package:meta/meta.dart';
|
import 'package:meta/meta.dart';
|
||||||
import 'package:redux/redux.dart';
|
import 'package:redux/redux.dart';
|
||||||
import 'package:redux_thunk/redux_thunk.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_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/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/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/journal_state.dart';
|
||||||
import 'package:satu/core/redux/state/sell_state.dart';
|
|
||||||
import 'package:satu/core/services/db_service.dart';
|
import 'package:satu/core/services/db_service.dart';
|
||||||
import 'package:satu/core/utils/locator.dart';
|
import 'package:satu/core/utils/locator.dart';
|
||||||
import 'package:satu/core/utils/logger.dart';
|
import 'package:satu/core/utils/logger.dart';
|
||||||
import 'package:uuid/uuid.dart';
|
|
||||||
|
|
||||||
import '../store.dart';
|
import '../store.dart';
|
||||||
|
|
||||||
|
|
@ -44,7 +37,6 @@ Future<void> loadJournalData(Store<AppState> store) async {
|
||||||
try {
|
try {
|
||||||
log.i('loadJournalData');
|
log.i('loadJournalData');
|
||||||
final int? appCompanyId = store.state.userState!.auth!.companyId;
|
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(
|
final List<Map<String, dynamic>> set = await _dbService.queryRowsWithWhere(
|
||||||
transactionTableName,
|
transactionTableName,
|
||||||
'$transactionColumnAppCompanyId = ?'
|
'$transactionColumnAppCompanyId = ?'
|
||||||
|
|
@ -75,7 +67,7 @@ Future<void> loadJournalData(Store<AppState> store) async {
|
||||||
dao.contragentName = data.contragentName;
|
dao.contragentName = data.contragentName;
|
||||||
dao.number = data.sellResponse?.journalId.toString() ?? '';
|
dao.number = data.sellResponse?.journalId.toString() ?? '';
|
||||||
dao.total = data.total;
|
dao.total = data.total;
|
||||||
if(transaction.type == transactionTypeReturnSell) {
|
if (transaction.type == transactionTypeReturnSell) {
|
||||||
dao.received = false;
|
dao.received = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -8,8 +8,8 @@ import '../store.dart';
|
||||||
|
|
||||||
@immutable
|
@immutable
|
||||||
class SetNavStateAction {
|
class SetNavStateAction {
|
||||||
final NavState navState;
|
|
||||||
SetNavStateAction(this.navState);
|
SetNavStateAction(this.navState);
|
||||||
|
final NavState navState;
|
||||||
}
|
}
|
||||||
|
|
||||||
ThunkAction<AppState> navigateDrawer(Type viewClass) {
|
ThunkAction<AppState> navigateDrawer(Type viewClass) {
|
||||||
|
|
|
||||||
|
|
@ -1,26 +1,11 @@
|
||||||
import 'dart:convert';
|
|
||||||
|
|
||||||
import 'package:intl/intl.dart';
|
|
||||||
import 'package:logger/logger.dart';
|
import 'package:logger/logger.dart';
|
||||||
import 'package:meta/meta.dart';
|
import 'package:meta/meta.dart';
|
||||||
import 'package:redux/redux.dart';
|
import 'package:redux/redux.dart';
|
||||||
import 'package:redux_thunk/redux_thunk.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/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/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:satu/core/utils/logger.dart';
|
||||||
import 'package:uuid/uuid.dart';
|
|
||||||
|
|
||||||
import '../store.dart';
|
import '../store.dart';
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -13,9 +13,9 @@ import '../store.dart';
|
||||||
|
|
||||||
@immutable
|
@immutable
|
||||||
class SetUserStateAction {
|
class SetUserStateAction {
|
||||||
final UserState userState;
|
|
||||||
|
|
||||||
SetUserStateAction(this.userState);
|
SetUserStateAction(this.userState);
|
||||||
|
final UserState userState;
|
||||||
}
|
}
|
||||||
|
|
||||||
final ApiService _api = locator<ApiService>();
|
final ApiService _api = locator<ApiService>();
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,5 @@
|
||||||
import 'package:satu/core/redux/actions/journal_actions.dart';
|
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/journal_state.dart';
|
||||||
import 'package:satu/core/redux/state/sell_state.dart';
|
|
||||||
import 'package:satu/core/redux/state/user_state.dart';
|
|
||||||
|
|
||||||
JournalState journalReducer(
|
JournalState journalReducer(
|
||||||
JournalState prevState, SetJournalStateAction action) {
|
JournalState prevState, SetJournalStateAction action) {
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,5 @@
|
||||||
import 'package:satu/core/redux/actions/nav_actions.dart';
|
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/nav_state.dart';
|
||||||
import 'package:satu/core/redux/state/user_state.dart';
|
|
||||||
|
|
||||||
NavState navReducer(NavState prevState, SetNavStateAction action) {
|
NavState navReducer(NavState prevState, SetNavStateAction action) {
|
||||||
final NavState payload = action.navState;
|
final NavState payload = action.navState;
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,5 @@
|
||||||
import 'package:satu/core/redux/actions/sell_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/sell_state.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) {
|
SellState sellReducer(SellState prevState, SetSellStateAction action) {
|
||||||
final SellState payload = action.sellState;
|
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/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/setting_state.dart';
|
||||||
import 'package:satu/core/redux/state/user_state.dart';
|
|
||||||
|
|
||||||
SettingState settingReducer(
|
SettingState settingReducer(
|
||||||
SettingState prevState, SetSettingStateAction action) {
|
SettingState prevState, SetSettingStateAction action) {
|
||||||
|
|
|
||||||
|
|
@ -3,8 +3,6 @@ import 'package:satu/views/work/work_view.dart';
|
||||||
|
|
||||||
@immutable
|
@immutable
|
||||||
class NavState {
|
class NavState {
|
||||||
final Type? drawerViewClass;
|
|
||||||
final int? selectedTabIndex;
|
|
||||||
|
|
||||||
NavState({this.drawerViewClass, this.selectedTabIndex});
|
NavState({this.drawerViewClass, this.selectedTabIndex});
|
||||||
|
|
||||||
|
|
@ -12,6 +10,8 @@ class NavState {
|
||||||
drawerViewClass: WorkView,
|
drawerViewClass: WorkView,
|
||||||
selectedTabIndex: 0,
|
selectedTabIndex: 0,
|
||||||
);
|
);
|
||||||
|
final Type? drawerViewClass;
|
||||||
|
final int? selectedTabIndex;
|
||||||
|
|
||||||
NavState copyWith({
|
NavState copyWith({
|
||||||
required int? selectedTabIndex,
|
required int? selectedTabIndex,
|
||||||
|
|
|
||||||
|
|
@ -1,23 +1,24 @@
|
||||||
import 'package:meta/meta.dart';
|
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/dao/product_dao.dart';
|
||||||
import 'package:satu/core/models/flow/transaction_state.dart';
|
import 'package:satu/core/models/flow/transaction_state.dart';
|
||||||
|
|
||||||
@immutable
|
@immutable
|
||||||
class SellState {
|
class SellState {
|
||||||
final List<ProductDao>? items;
|
|
||||||
final TransactionState? transactionState;
|
|
||||||
|
|
||||||
SellState({this.items, this.transactionState});
|
|
||||||
|
|
||||||
factory SellState.initial() => SellState(
|
factory SellState.initial() => SellState(
|
||||||
items: [],
|
items: [],
|
||||||
transactionState: TransactionState(),
|
transactionState: TransactionState(),
|
||||||
);
|
);
|
||||||
|
|
||||||
SellState copyWith({required List<ProductDao>? items, required TransactionState? transactionState}) {
|
SellState({this.items, this.transactionState});
|
||||||
return SellState(items: items ?? this.items, transactionState: transactionState ?? 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:meta/meta.dart';
|
||||||
import 'package:satu/core/models/flow/dao/transaction_dao.dart';
|
|
||||||
import 'package:satu/core/models/settings/printer_setting.dart';
|
import 'package:satu/core/models/settings/printer_setting.dart';
|
||||||
|
|
||||||
@immutable
|
@immutable
|
||||||
class SettingState {
|
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});
|
const SettingState({this.printer});
|
||||||
|
|
||||||
factory SettingState.initial(SettingState? settingState) =>
|
factory SettingState.initial(SettingState? settingState) =>
|
||||||
|
|
@ -20,13 +28,4 @@ class SettingState {
|
||||||
'printer': printer !=null ? printer!.toMap() : null,
|
'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
|
@immutable
|
||||||
class UserState {
|
class UserState {
|
||||||
final bool? isError;
|
|
||||||
final bool? isLoading;
|
factory UserState.initial(UserState? payload) => UserState(
|
||||||
final AuthResponse? auth;
|
isLoading: false,
|
||||||
|
isError: false,
|
||||||
|
auth: payload?.auth ?? (AuthResponse()..operation=false),
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
UserState(
|
UserState(
|
||||||
|
|
@ -15,12 +18,9 @@ class UserState {
|
||||||
this.isLoading,
|
this.isLoading,
|
||||||
this.auth,
|
this.auth,
|
||||||
});
|
});
|
||||||
|
final bool? isError;
|
||||||
factory UserState.initial(UserState? payload) => UserState(
|
final bool? isLoading;
|
||||||
isLoading: false,
|
final AuthResponse? auth;
|
||||||
isError: false,
|
|
||||||
auth: payload?.auth ?? (AuthResponse()..operation=false),
|
|
||||||
);
|
|
||||||
|
|
||||||
UserState copyWith({
|
UserState copyWith({
|
||||||
required bool? isError,
|
required bool? isError,
|
||||||
|
|
|
||||||
|
|
@ -120,7 +120,8 @@ class Redux {
|
||||||
final navStateInitial = NavState.initial();
|
final navStateInitial = NavState.initial();
|
||||||
final sellStateInitial = SellState.initial();
|
final sellStateInitial = SellState.initial();
|
||||||
final journalStateInitial = JournalState.initial();
|
final journalStateInitial = JournalState.initial();
|
||||||
final settingStateInitial = SettingState.initial(initialState?.settingState);
|
final settingStateInitial =
|
||||||
|
SettingState.initial(initialState?.settingState);
|
||||||
|
|
||||||
_store = Store<AppState>(
|
_store = Store<AppState>(
|
||||||
appReducer,
|
appReducer,
|
||||||
|
|
|
||||||
|
|
@ -4,18 +4,18 @@ import 'dart:io';
|
||||||
import 'package:satu/core/base/base_service.dart';
|
import 'package:satu/core/base/base_service.dart';
|
||||||
import 'package:http/http.dart' as http;
|
import 'package:http/http.dart' as http;
|
||||||
import 'package:satu/core/models/auth/auth_response.dart';
|
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/analytics/analytics_bean.dart';
|
||||||
import 'package:satu/core/models/flow/sell_request.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_response.dart';
|
||||||
import 'package:satu/core/models/flow/sell_return/sell_return_request.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
|
/// The service responsible for networking requests
|
||||||
class ApiService extends BaseService {
|
class ApiService extends BaseService {
|
||||||
static const host = 'satu.aman.com.kz';
|
static const host = 'satu.aman.com.kz';
|
||||||
static const endpoint = '/api/v1';
|
static const endpoint = '/api/v1';
|
||||||
|
|
||||||
http.Client client = http.Client();
|
|
||||||
|
|
||||||
//TOKEN
|
//TOKEN
|
||||||
String? token;
|
String? token;
|
||||||
|
|
@ -38,15 +38,18 @@ class ApiService extends BaseService {
|
||||||
{Map<String, dynamic>? requestBody, Map<String, String>? header}) async {
|
{Map<String, dynamic>? requestBody, Map<String, String>? header}) async {
|
||||||
final Map<String, String> headers = <String, String>{
|
final Map<String, String> headers = <String, String>{
|
||||||
HttpHeaders.contentTypeHeader: 'application/json',
|
HttpHeaders.contentTypeHeader: 'application/json',
|
||||||
HttpHeaders.cacheControlHeader: 'no-cache'
|
HttpHeaders.cacheControlHeader: 'no-cache',
|
||||||
};
|
};
|
||||||
if (header != null && header.isNotEmpty) {
|
if (header != null && header.isNotEmpty) {
|
||||||
headers.addAll(header);
|
headers.addAll(header);
|
||||||
}
|
}
|
||||||
final String url = '$endpoint$point';
|
final String url = '$endpoint$point';
|
||||||
if (requestBody != null) {
|
// if (requestBody != null) {
|
||||||
log.i(jsonEncode(requestBody));
|
// log.i(host);
|
||||||
}
|
// log.i(url);
|
||||||
|
// log.i(headers);
|
||||||
|
// log.i(jsonEncode(requestBody));
|
||||||
|
// }
|
||||||
final response = await http.post(Uri.https(host, url),
|
final response = await http.post(Uri.https(host, url),
|
||||||
body: jsonEncode(requestBody), headers: headers);
|
body: jsonEncode(requestBody), headers: headers);
|
||||||
|
|
||||||
|
|
@ -121,36 +124,55 @@ class ApiService extends BaseService {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<Response> dictionaries(String target) async {
|
Future<DictResponseEntity> dictionaries(String target,
|
||||||
Response result;
|
{Map<String, dynamic>? requestBody}) async {
|
||||||
|
DictResponseEntity result;
|
||||||
try {
|
try {
|
||||||
final Map<String, String> headers = <String, String>{
|
final Map<String, String> headers = <String, String>{
|
||||||
HttpHeaders.authorizationHeader: 'Bearer $token'
|
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) {
|
} catch (e, stack) {
|
||||||
log.e('dictionaries', e, stack);
|
log.e('dictionaries', e, stack);
|
||||||
result = Response()
|
result = DictResponseEntity()..exception = e.toString();
|
||||||
..operation = false
|
|
||||||
..list = [];
|
|
||||||
}
|
}
|
||||||
return result;
|
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 {
|
Future<SellResponse> sell(SellRequest request) async {
|
||||||
SellResponse response;
|
SellResponse response;
|
||||||
try {
|
try {
|
||||||
final Map<String, String> headers = <String, String>{
|
final Map<String, String> headers = <String, String>{
|
||||||
HttpHeaders.authorizationHeader: 'Bearer $token'
|
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));
|
response = SellResponse.fromMap(json.decode(responseBody));
|
||||||
} catch (e, stack) {
|
} catch (e, stack) {
|
||||||
log.e('dictionaries', e, stack);
|
log.e('dictionaries', e, stack);
|
||||||
response = SellResponse()
|
response = SellResponse()
|
||||||
..operation = false
|
..operation = false
|
||||||
..message = e.toString();
|
..message = e.toString();
|
||||||
}
|
}
|
||||||
return response;
|
return response;
|
||||||
}
|
}
|
||||||
|
|
@ -161,7 +183,8 @@ class ApiService extends BaseService {
|
||||||
final Map<String, String> headers = <String, String>{
|
final Map<String, String> headers = <String, String>{
|
||||||
HttpHeaders.authorizationHeader: 'Bearer $token'
|
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));
|
response = SellResponse.fromMap(json.decode(responseBody));
|
||||||
} catch (e, stack) {
|
} catch (e, stack) {
|
||||||
log.e('sellReturn', e, stack);
|
log.e('sellReturn', e, stack);
|
||||||
|
|
@ -179,7 +202,6 @@ class ApiService extends BaseService {
|
||||||
HttpHeaders.authorizationHeader: 'Bearer $token'
|
HttpHeaders.authorizationHeader: 'Bearer $token'
|
||||||
};
|
};
|
||||||
final String responseBody = await _get('/get_analytics', header: headers);
|
final String responseBody = await _get('/get_analytics', header: headers);
|
||||||
log.i(responseBody);
|
|
||||||
response = AnalyticsBean.fromMap(json.decode(responseBody));
|
response = AnalyticsBean.fromMap(json.decode(responseBody));
|
||||||
} catch (e, stack) {
|
} catch (e, stack) {
|
||||||
log.e('getAnalytics', e, stack);
|
log.e('getAnalytics', e, stack);
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,5 @@
|
||||||
import 'dart:convert';
|
import 'dart:convert';
|
||||||
|
|
||||||
import 'package:flutter/material.dart';
|
|
||||||
import 'package:satu/core/base/base_service.dart';
|
import 'package:satu/core/base/base_service.dart';
|
||||||
import 'package:satu/core/entity/transaction_entity.dart';
|
import 'package:satu/core/entity/transaction_entity.dart';
|
||||||
import 'package:satu/core/models/entity_data/transaction_data.dart';
|
import 'package:satu/core/models/entity_data/transaction_data.dart';
|
||||||
|
|
@ -160,7 +159,6 @@ class DataService extends BaseService {
|
||||||
transaction.data = jsonEncode(data.toMap());
|
transaction.data = jsonEncode(data.toMap());
|
||||||
log.i(jsonEncode(data.toMap()));
|
log.i(jsonEncode(data.toMap()));
|
||||||
return await _db.insert(transactionTableName, transaction.toMap());
|
return await _db.insert(transactionTableName, transaction.toMap());
|
||||||
;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ItemBean _productToItemBean(ProductDao product) {
|
ItemBean _productToItemBean(ProductDao product) {
|
||||||
|
|
|
||||||
|
|
@ -10,11 +10,11 @@ import 'package:path/path.dart';
|
||||||
import 'package:path_provider/path_provider.dart';
|
import 'package:path_provider/path_provider.dart';
|
||||||
|
|
||||||
class DbService extends BaseService {
|
class DbService extends BaseService {
|
||||||
static const _databaseName = 'AmanSatuDb.db';
|
|
||||||
static const _databaseVersion = 2;
|
|
||||||
|
|
||||||
// make this a singleton class
|
// make this a singleton class
|
||||||
DbService._privateConstructor();
|
DbService._privateConstructor();
|
||||||
|
static const _databaseName = 'AmanSatuDb.db';
|
||||||
|
static const _databaseVersion = 2;
|
||||||
|
|
||||||
static final DbService instance = DbService._privateConstructor();
|
static final DbService instance = DbService._privateConstructor();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -21,7 +21,8 @@ class DialogService {
|
||||||
_showDialogInputListener = showDialogInputListener;
|
_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({
|
Future<DialogResponse> showDialog({
|
||||||
String title = 'SATU',
|
String title = 'SATU',
|
||||||
String? description,
|
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/category_entity.dart';
|
||||||
import 'package:satu/core/entity/goods_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_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/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/redux/store.dart';
|
||||||
import 'package:satu/core/utils/locator.dart';
|
import 'package:satu/core/utils/locator.dart';
|
||||||
|
|
||||||
|
|
@ -15,32 +16,10 @@ class DictionaryService extends BaseService {
|
||||||
final DbService _db = locator<DbService>();
|
final DbService _db = locator<DbService>();
|
||||||
|
|
||||||
Future<void> refreshFull() async {
|
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 {
|
Future<List<Category>> getCategoryByParentId(int parentId) async {
|
||||||
final List<Category> list = [];
|
final List<Category> list = [];
|
||||||
|
|
@ -77,23 +56,7 @@ class DictionaryService extends BaseService {
|
||||||
return result;
|
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 {
|
Future<List<Good>> getGoodsByCategoryId(int categoryId) async {
|
||||||
final List<Good> list = [];
|
final List<Good> list = [];
|
||||||
|
|
@ -134,55 +97,126 @@ class DictionaryService extends BaseService {
|
||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<List<Good>> getGoodsByEan(String code) async {
|
bool _isNumericInt(String? str) {
|
||||||
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) {
|
|
||||||
if (str == null) {
|
if (str == null) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return int.tryParse(str) != null;
|
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 {
|
try {
|
||||||
int? appCompanyId = Redux.store!.state.userState!.auth!.companyId;
|
final Map<String, dynamic> requestBody = <String, dynamic>{
|
||||||
Response categories = await _api.dictionaries('/goods');
|
'page': page,
|
||||||
if (categories.operation! && categories.list!.isNotEmpty) {
|
'perpage': perpage,
|
||||||
for (final dynamic map in categories.list!) {
|
'filter': [
|
||||||
final GoodResponse good = GoodResponse.fromMap(map);
|
{'col': 'name', 'action': 'like', 'val': query ?? ''}
|
||||||
final Good entity = new Good()
|
]
|
||||||
..id = good.id
|
};
|
||||||
..name = good.name
|
|
||||||
..categoryId = good.categoryId
|
DictResponseEntity categories =
|
||||||
..ean = good.ean
|
await _api.dictionaries('/goods_categories_get', requestBody: requestBody);
|
||||||
..articul = good.articul
|
if (categories.original.data != null &&
|
||||||
..price = good.price
|
categories.original.data!.isNotEmpty) {
|
||||||
..optPrice = good.optPrice
|
for (final dynamic map in categories.original.data!) {
|
||||||
..basePrice = good.basePrice
|
final CategoryResponse good = CategoryResponse.fromMap(map);
|
||||||
..divisible = good.divisible
|
list.add(good);
|
||||||
..updatedAt = good.updatedAt
|
|
||||||
..appCompanyId = appCompanyId;
|
|
||||||
_db.insert(goodTableName, entity.toMap());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (e, stack) {
|
} 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}) {
|
Future<dynamic> replace(String routeName, {dynamic arguments}) {
|
||||||
log.d('routeName: $routeName');
|
log.d('routeName: $routeName');
|
||||||
return navigatorKey.currentState!
|
return navigatorKey.currentState!.pushNamedAndRemoveUntil(
|
||||||
.pushNamedAndRemoveUntil(routeName, (Route<dynamic> route) => false, arguments: arguments);
|
routeName, (Route<dynamic> route) => false,
|
||||||
|
arguments: arguments);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Future<T?> navigateToPage<T>(MaterialPageRoute<T> pageRoute) async {
|
Future<T?> navigateToPage<T>(MaterialPageRoute<T> pageRoute) async {
|
||||||
log.d('navigateToPage: pageRoute: ${pageRoute.settings.name}');
|
log.d('navigateToPage: pageRoute: ${pageRoute.settings.name}');
|
||||||
if (navigatorKey.currentState == null) {
|
if (navigatorKey.currentState == null) {
|
||||||
|
|
@ -31,7 +31,7 @@ class NavigatorService extends BaseService {
|
||||||
Future<T?> navigateToPageWithReplacement<T>(
|
Future<T?> navigateToPageWithReplacement<T>(
|
||||||
MaterialPageRoute<T> pageRoute) async {
|
MaterialPageRoute<T> pageRoute) async {
|
||||||
log.d('navigateToPageWithReplacement: '
|
log.d('navigateToPageWithReplacement: '
|
||||||
'pageRoute: ${pageRoute.settings.name}');
|
'pageRoute: ${pageRoute.settings.name}');
|
||||||
if (navigatorKey.currentState == null) {
|
if (navigatorKey.currentState == null) {
|
||||||
log.e('navigateToPageWithReplacement: Navigator State is null');
|
log.e('navigateToPageWithReplacement: Navigator State is null');
|
||||||
return null;
|
return null;
|
||||||
|
|
|
||||||
|
|
@ -2,10 +2,10 @@ import 'dart:convert';
|
||||||
import 'package:logger/logger.dart';
|
import 'package:logger/logger.dart';
|
||||||
|
|
||||||
class SimpleLogPrinter extends LogPrinter {
|
class SimpleLogPrinter extends LogPrinter {
|
||||||
|
SimpleLogPrinter(this.className);
|
||||||
final String className;
|
final String className;
|
||||||
static final _deviceStackTraceRegex = RegExp(r'#[0-9]+[\s]+(.+) \(([^\s]+)\)');
|
static final _deviceStackTraceRegex = RegExp(r'#[0-9]+[\s]+(.+) \(([^\s]+)\)');
|
||||||
static final _webStackTraceRegex = RegExp(r'^((packages|dart-sdk)\/[^\s]+\/)');
|
static final _webStackTraceRegex = RegExp(r'^((packages|dart-sdk)\/[^\s]+\/)');
|
||||||
SimpleLogPrinter(this.className);
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
List<String> log(LogEvent event) {
|
List<String> log(LogEvent event) {
|
||||||
|
|
|
||||||
|
|
@ -10,8 +10,6 @@ const String addByBarcodeViewRoute = 'AddByBarcodeView';
|
||||||
const String paymentViewRoute = 'paymentViewRoute';
|
const String paymentViewRoute = 'paymentViewRoute';
|
||||||
const String receiptViewRoute = 'receiptViewRoute';
|
const String receiptViewRoute = 'receiptViewRoute';
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// dictionaries - category
|
// dictionaries - category
|
||||||
const String categoryEditRoute = 'categoryEditRoute';
|
const String categoryEditRoute = 'categoryEditRoute';
|
||||||
const String categorySelectViewRoute = 'categorySelectViewRoute';
|
const String categorySelectViewRoute = 'categorySelectViewRoute';
|
||||||
|
|
@ -20,10 +18,13 @@ const String goodsEditRoute = 'goodsEditRoute';
|
||||||
const String goodsDictionaryViewRoute = 'goodsDictionaryViewRoute';
|
const String goodsDictionaryViewRoute = 'goodsDictionaryViewRoute';
|
||||||
//dictionaries - contragent
|
//dictionaries - contragent
|
||||||
const String contragentSelectViewRoute = 'ContragentSelectViewRoute';
|
const String contragentSelectViewRoute = 'ContragentSelectViewRoute';
|
||||||
|
const String contragentEditRoute = 'contragentEditRoute';
|
||||||
|
|
||||||
// setting - ble printer
|
// setting - ble printer
|
||||||
const String settingPrinterBluetoothViewRoute = 'SettingPrinterBluetoothView';
|
const String settingPrinterBluetoothViewRoute = 'SettingPrinterBluetoothView';
|
||||||
const String settingPrinterBluetoothSelectViewRoute = 'settingPrinterBluetoothSelectViewRoute';
|
const String settingPrinterBluetoothSelectViewRoute =
|
||||||
const String settingPrinterPaperSizeViewRoute = 'settingPrinterPaperSizeViewRoute';
|
'settingPrinterBluetoothSelectViewRoute';
|
||||||
const String settingPrinterEncodingViewRoute = 'settingPrinterEncodingViewRoute';
|
const String settingPrinterPaperSizeViewRoute =
|
||||||
|
'settingPrinterPaperSizeViewRoute';
|
||||||
|
const String settingPrinterEncodingViewRoute =
|
||||||
|
'settingPrinterEncodingViewRoute';
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,12 @@
|
||||||
import 'package:flutter/material.dart';
|
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/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/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_edit.dart';
|
||||||
import 'package:satu/views/dictionaries/category/category_select_view.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/dictionaries/goods/goods_edit.dart';
|
||||||
import 'package:satu/views/login/login_view.dart';
|
import 'package:satu/views/login/login_view.dart';
|
||||||
import 'package:satu/views/main/main_view.dart';
|
import 'package:satu/views/main/main_view.dart';
|
||||||
|
|
@ -73,13 +76,20 @@ Route<dynamic> generateRoute(RouteSettings settings) {
|
||||||
routeName: settings.name,
|
routeName: settings.name,
|
||||||
viewToShow: SelectContragentView(),
|
viewToShow: SelectContragentView(),
|
||||||
);
|
);
|
||||||
|
case contragentEditRoute:
|
||||||
|
final ContragentResponseEntity contragent =
|
||||||
|
settings.arguments! as ContragentResponseEntity;
|
||||||
|
return _getPageRoute(
|
||||||
|
routeName: settings.name,
|
||||||
|
viewToShow: ContragentEdit(contragent: contragent),
|
||||||
|
);
|
||||||
case paymentViewRoute:
|
case paymentViewRoute:
|
||||||
return _getPageRoute(
|
return _getPageRoute(
|
||||||
routeName: settings.name,
|
routeName: settings.name,
|
||||||
viewToShow: const PaymentView(),
|
viewToShow: const PaymentView(),
|
||||||
);
|
);
|
||||||
case categoryEditRoute:
|
case categoryEditRoute:
|
||||||
final CategoryRowDao category = settings.arguments! as CategoryRowDao;
|
final CategoryResponse category = settings.arguments! as CategoryResponse;
|
||||||
return _getPageRoute(
|
return _getPageRoute(
|
||||||
routeName: settings.name,
|
routeName: settings.name,
|
||||||
viewToShow: CategoryEdit(
|
viewToShow: CategoryEdit(
|
||||||
|
|
@ -92,7 +102,7 @@ Route<dynamic> generateRoute(RouteSettings settings) {
|
||||||
viewToShow: CategorySelectView(),
|
viewToShow: CategorySelectView(),
|
||||||
);
|
);
|
||||||
case goodsEditRoute:
|
case goodsEditRoute:
|
||||||
final GoodRowDao good = settings.arguments! as GoodRowDao;
|
final GoodResponse good = settings.arguments! as GoodResponse;
|
||||||
return _getPageRoute(
|
return _getPageRoute(
|
||||||
routeName: settings.name,
|
routeName: settings.name,
|
||||||
viewToShow: GoodEdit(
|
viewToShow: GoodEdit(
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@ import 'package:flutter/material.dart';
|
||||||
import 'package:logger/logger.dart';
|
import 'package:logger/logger.dart';
|
||||||
import 'package:satu/core/entity/category_entity.dart';
|
import 'package:satu/core/entity/category_entity.dart';
|
||||||
import 'package:satu/core/models/dialog_models.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/models/dictionary/category_row_data.dart';
|
||||||
import 'package:satu/core/services/dialog_service.dart';
|
import 'package:satu/core/services/dialog_service.dart';
|
||||||
import 'package:satu/core/services/dictionary_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/core/utils/logger.dart';
|
||||||
import 'package:satu/routes/route_names.dart';
|
import 'package:satu/routes/route_names.dart';
|
||||||
import 'package:satu/shared/ui_helpers.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/bar/products_app_bar.dart';
|
||||||
import 'package:satu/widgets/buttons/busy_button.dart';
|
import 'package:satu/widgets/buttons/busy_button.dart';
|
||||||
import 'package:satu/widgets/fields/input_field.dart';
|
import 'package:satu/widgets/fields/input_field.dart';
|
||||||
import 'package:satu/widgets/fields/line_tile.dart';
|
import 'package:satu/widgets/fields/line_tile.dart';
|
||||||
import 'package:satu/widgets/fields/note_text.dart';
|
|
||||||
|
|
||||||
class CategoryEdit extends StatefulWidget {
|
class CategoryEdit extends StatefulWidget {
|
||||||
const CategoryEdit({
|
const CategoryEdit({
|
||||||
required this.category,
|
required this.category,
|
||||||
Key? key,
|
Key? key,
|
||||||
}) : super(key: key);
|
}) : super(key: key);
|
||||||
final CategoryRowDao category;
|
final CategoryResponse category;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
_CategoryEditState createState() => _CategoryEditState();
|
_CategoryEditState createState() => _CategoryEditState();
|
||||||
|
|
@ -35,18 +34,17 @@ class _CategoryEditState extends State<CategoryEdit> {
|
||||||
final Logger log = getLogger('_CategoryEditState');
|
final Logger log = getLogger('_CategoryEditState');
|
||||||
late TextEditingController _controller;
|
late TextEditingController _controller;
|
||||||
|
|
||||||
String parentCategoryName = '';
|
String? parentCategoryName;
|
||||||
int parentCategoryId = 0;
|
int? parentCategoryId;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
if (widget.category.parentId != null) {
|
if (widget.category.parentId != null) {
|
||||||
parentCategoryId = widget.category.parentId!;
|
parentCategoryId = widget.category.parentId;
|
||||||
|
parentCategoryName = widget.category.parentId.toString();
|
||||||
}
|
}
|
||||||
_controller = TextEditingController(text: widget.category.name);
|
_controller = TextEditingController(text: widget.category.name);
|
||||||
|
|
||||||
getAndStateCategoryName(parentCategoryId);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
|
@ -55,24 +53,7 @@ class _CategoryEditState extends State<CategoryEdit> {
|
||||||
super.dispose();
|
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
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
|
|
@ -89,7 +70,7 @@ class _CategoryEditState extends State<CategoryEdit> {
|
||||||
children: [
|
children: [
|
||||||
verticalSpaceSmall,
|
verticalSpaceSmall,
|
||||||
LineTile(
|
LineTile(
|
||||||
parentCategoryName,
|
parentCategoryName ?? 'Корневая категория',
|
||||||
onTap: selectCategory,
|
onTap: selectCategory,
|
||||||
labelText: 'Родительская категория',
|
labelText: 'Родительская категория',
|
||||||
),
|
),
|
||||||
|
|
@ -133,8 +114,11 @@ class _CategoryEditState extends State<CategoryEdit> {
|
||||||
Future<void> selectCategory() async {
|
Future<void> selectCategory() async {
|
||||||
final dynamic result =
|
final dynamic result =
|
||||||
await _navigatorService.push(categorySelectViewRoute);
|
await _navigatorService.push(categorySelectViewRoute);
|
||||||
if (result != null) {
|
CategoryResponse? category = result as CategoryResponse?;
|
||||||
getAndStateCategoryName(result as int);
|
setState(() {
|
||||||
}
|
parentCategoryId = category?.id;
|
||||||
|
parentCategoryName = category?.name;
|
||||||
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,13 +1,13 @@
|
||||||
|
import 'dart:async';
|
||||||
|
|
||||||
import 'package:flutter/material.dart';
|
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/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/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/dictionary_service.dart';
|
||||||
import 'package:satu/core/services/navigator_service.dart';
|
import 'package:satu/core/services/navigator_service.dart';
|
||||||
import 'package:satu/core/utils/locator.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/app_colors.dart';
|
||||||
import 'package:satu/shared/ui_helpers.dart';
|
import 'package:satu/shared/ui_helpers.dart';
|
||||||
import 'package:satu/views/dictionaries/component/dictionary_list_tile.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/input_field.dart';
|
||||||
import 'package:satu/widgets/fields/line_checkbox.dart';
|
import 'package:satu/widgets/fields/line_checkbox.dart';
|
||||||
|
|
||||||
import 'category_view.dart';
|
|
||||||
|
|
||||||
class CategorySelectView extends StatefulWidget {
|
class CategorySelectView extends StatefulWidget {
|
||||||
@override
|
@override
|
||||||
_CategorySelectViewState createState() => _CategorySelectViewState();
|
_CategorySelectViewState createState() => _CategorySelectViewState();
|
||||||
|
|
@ -29,38 +27,41 @@ class _CategorySelectViewState extends State<CategorySelectView> {
|
||||||
late TextEditingController _searchTextController;
|
late TextEditingController _searchTextController;
|
||||||
final FocusNode _searchFocusNode = FocusNode();
|
final FocusNode _searchFocusNode = FocusNode();
|
||||||
|
|
||||||
late List<Category> _categories = [];
|
static const _pageSize = 20;
|
||||||
|
String query = '';
|
||||||
late List<CategoryRowDao> items = [];
|
Timer? _debounce;
|
||||||
|
final PagingController<int, CategoryResponse> _pagingController =
|
||||||
|
PagingController(firstPageKey: 1);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
_searchTextController = TextEditingController();
|
_searchTextController = TextEditingController();
|
||||||
_searchTextController.addListener(() {
|
_searchTextController.addListener(() {
|
||||||
if (_searchTextController.text.isNotEmpty) {
|
setState(() {
|
||||||
searchByField(_searchTextController.text);
|
query = _searchTextController.text;
|
||||||
} else {
|
});
|
||||||
reset();
|
if (_debounce?.isActive ?? false) _debounce?.cancel();
|
||||||
}
|
_debounce = Timer(const Duration(milliseconds: 500), () {
|
||||||
|
_pagingController.refresh();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
_pagingController.addPageRequestListener((pageKey) {
|
||||||
|
_fetchData(pageKey, _pageSize, query);
|
||||||
});
|
});
|
||||||
initQuery();
|
|
||||||
super.initState();
|
super.initState();
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> initQuery() async {
|
|
||||||
_categories = await _dictionaryService.getCategoriesAll();
|
|
||||||
searchByField('');
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void dispose() {
|
void dispose() {
|
||||||
|
_debounce?.cancel();
|
||||||
|
_pagingController.dispose();
|
||||||
_searchTextController.dispose();
|
_searchTextController.dispose();
|
||||||
_searchFocusNode.dispose();
|
_searchFocusNode.dispose();
|
||||||
super.dispose();
|
super.dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> handlerCategory(int id) async {
|
Future<void> handlerCategory(CategoryResponse? category) async {
|
||||||
_navigatorService.pop(id);
|
_navigatorService.pop(category);
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
|
@ -82,43 +83,47 @@ class _CategorySelectViewState extends State<CategorySelectView> {
|
||||||
'Корневая категория',
|
'Корневая категория',
|
||||||
value: true,
|
value: true,
|
||||||
labelText: 'По умолчанию',
|
labelText: 'По умолчанию',
|
||||||
onTap: () => handlerCategory(0),
|
onTap: () => handlerCategory(null),
|
||||||
),
|
),
|
||||||
const ProductsTitleBarBar(title: 'Выберите категорию'),
|
const ProductsTitleBarBar(title: 'Выберите категорию'),
|
||||||
Expanded(
|
Expanded(
|
||||||
child: ListView.separated(
|
child: PagedListView<int, CategoryResponse>.separated(
|
||||||
physics: const BouncingScrollPhysics(),
|
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) {
|
separatorBuilder: (BuildContext context, int index) {
|
||||||
return const Divider(
|
return const Divider(
|
||||||
height: 1.0,
|
height: 1.0,
|
||||||
color: disableColor,
|
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() {
|
void reset() {
|
||||||
_searchTextController.clear();
|
_searchTextController.clear();
|
||||||
searchByField('');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void searchByField(String query) async {
|
Future<void> _fetchData(int pageKey, int perPage, String? query) async {
|
||||||
final List<CategoryRowDao> list = [];
|
final List<CategoryResponse> newItems = await _dictionaryService
|
||||||
final Iterable<Category> filtered = query == ''
|
.getCategories(page: pageKey, query: query, perpage: perPage);
|
||||||
? _categories
|
|
||||||
: _categories.where((element) =>
|
final isLastPage = newItems.length < _pageSize;
|
||||||
element.name.toLowerCase().contains(query.toLowerCase()));
|
if (isLastPage) {
|
||||||
filtered.forEach((element) {
|
_pagingController.appendLastPage(newItems);
|
||||||
final Category category = _categories
|
} else {
|
||||||
.firstWhere((parent) => parent.id == element.parentId, orElse: () {
|
final nextPageKey = pageKey + 1;
|
||||||
return Category();
|
_pagingController.appendPage(newItems, nextPageKey);
|
||||||
});
|
}
|
||||||
final String parentName = category.name;
|
|
||||||
final CategoryRowDao rowDao = CategoryRowDao(
|
|
||||||
element.name, parentName, element.id,
|
|
||||||
parentId: element.parentId);
|
|
||||||
list.add(rowDao);
|
|
||||||
});
|
|
||||||
setState(() {
|
|
||||||
items = list;
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,15 +1,16 @@
|
||||||
|
import 'dart:async';
|
||||||
|
|
||||||
import 'package:flutter/material.dart';
|
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/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/models/dictionary/category_row_data.dart';
|
||||||
import 'package:satu/core/redux/actions/sell_actions.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/dictionary_service.dart';
|
||||||
import 'package:satu/core/services/navigator_service.dart';
|
import 'package:satu/core/services/navigator_service.dart';
|
||||||
import 'package:satu/core/utils/locator.dart';
|
import 'package:satu/core/utils/locator.dart';
|
||||||
import 'package:satu/routes/route_names.dart';
|
import 'package:satu/routes/route_names.dart';
|
||||||
import 'package:satu/shared/app_colors.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/views/dictionaries/component/dictionary_list_tile.dart';
|
||||||
import 'package:satu/widgets/bar/products_app_bar.dart';
|
import 'package:satu/widgets/bar/products_app_bar.dart';
|
||||||
import 'package:satu/widgets/bar/products_title_bar.dart';
|
import 'package:satu/widgets/bar/products_title_bar.dart';
|
||||||
|
|
@ -26,31 +27,36 @@ class _CategoryDictionaryViewState extends State<CategoryDictionaryView> {
|
||||||
late TextEditingController _searchTextController;
|
late TextEditingController _searchTextController;
|
||||||
final FocusNode _searchFocusNode = new FocusNode();
|
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
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
_searchTextController = TextEditingController();
|
_searchTextController = TextEditingController();
|
||||||
_searchTextController.addListener(() {
|
_searchTextController.addListener(() {
|
||||||
if (_searchTextController.text.isNotEmpty) {
|
setState(() {
|
||||||
searchByField(_searchTextController.text);
|
query = _searchTextController.text;
|
||||||
} else {
|
});
|
||||||
reset();
|
if (_debounce?.isActive ?? false) _debounce?.cancel();
|
||||||
}
|
_debounce = Timer(const Duration(milliseconds: 500), () {
|
||||||
|
_pagingController.refresh();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
_pagingController.addPageRequestListener((pageKey) {
|
||||||
|
_fetchData(pageKey, _pageSize, query);
|
||||||
});
|
});
|
||||||
initQuery();
|
|
||||||
super.initState();
|
super.initState();
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> initQuery() async {
|
|
||||||
_categories = await _dictionaryService.getCategoriesAll();
|
|
||||||
searchByField('');
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void dispose() {
|
void dispose() {
|
||||||
|
_debounce?.cancel();
|
||||||
|
_pagingController.dispose();
|
||||||
_searchTextController.dispose();
|
_searchTextController.dispose();
|
||||||
_searchFocusNode.dispose();
|
_searchFocusNode.dispose();
|
||||||
super.dispose();
|
super.dispose();
|
||||||
|
|
@ -73,40 +79,43 @@ class _CategoryDictionaryViewState extends State<CategoryDictionaryView> {
|
||||||
),
|
),
|
||||||
const ProductsTitleBarBar(title: 'Список категории'),
|
const ProductsTitleBarBar(title: 'Список категории'),
|
||||||
Expanded(
|
Expanded(
|
||||||
child: ListView.separated(
|
child: PagedListView<int, CategoryResponse>.separated(
|
||||||
physics: const BouncingScrollPhysics(),
|
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) {
|
separatorBuilder: (BuildContext context, int index) {
|
||||||
return const Divider(
|
return const Divider(
|
||||||
height: 1.0,
|
height: 1.0,
|
||||||
color: disableColor,
|
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(
|
floatingActionButton: FloatingActionButton(
|
||||||
|
|
@ -124,30 +133,18 @@ class _CategoryDictionaryViewState extends State<CategoryDictionaryView> {
|
||||||
|
|
||||||
void reset() {
|
void reset() {
|
||||||
_searchTextController.clear();
|
_searchTextController.clear();
|
||||||
searchByField('');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void searchByField(String query) async {
|
Future<void> _fetchData(int pageKey, int perPage, String? query) async {
|
||||||
log.i(query);
|
final List<CategoryResponse> newItems = await _dictionaryService
|
||||||
final List<CategoryRowDao> list = [];
|
.getCategories(page: pageKey, query: query, perpage: perPage);
|
||||||
final Iterable<Category> filtered = query == ''
|
|
||||||
? _categories
|
final isLastPage = newItems.length < _pageSize;
|
||||||
: _categories.where((element) =>
|
if (isLastPage) {
|
||||||
element.name.toLowerCase().contains(query.toLowerCase()));
|
_pagingController.appendLastPage(newItems);
|
||||||
filtered.forEach((element) {
|
} else {
|
||||||
final Category category = _categories
|
final nextPageKey = pageKey + 1;
|
||||||
.firstWhere((parent) => parent.id == element.parentId, orElse: () {
|
_pagingController.appendPage(newItems, nextPageKey);
|
||||||
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;
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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:logger/logger.dart';
|
||||||
import 'package:satu/core/entity/category_entity.dart';
|
import 'package:satu/core/entity/category_entity.dart';
|
||||||
import 'package:satu/core/models/dialog_models.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/models/dictionary/good_row_data.dart';
|
||||||
import 'package:satu/core/services/dialog_service.dart';
|
import 'package:satu/core/services/dialog_service.dart';
|
||||||
import 'package:satu/core/services/dictionary_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/core/utils/logger.dart';
|
||||||
import 'package:satu/routes/route_names.dart';
|
import 'package:satu/routes/route_names.dart';
|
||||||
import 'package:satu/shared/ui_helpers.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/bar/products_app_bar.dart';
|
||||||
import 'package:satu/widgets/buttons/busy_button.dart';
|
import 'package:satu/widgets/buttons/busy_button.dart';
|
||||||
import 'package:satu/widgets/fields/input_field.dart';
|
import 'package:satu/widgets/fields/input_field.dart';
|
||||||
import 'package:satu/widgets/fields/line_tile.dart';
|
import 'package:satu/widgets/fields/line_tile.dart';
|
||||||
import 'package:satu/widgets/fields/note_text.dart';
|
|
||||||
|
|
||||||
class GoodEdit extends StatefulWidget {
|
class GoodEdit extends StatefulWidget {
|
||||||
const GoodEdit({
|
const GoodEdit({
|
||||||
required this.good,
|
required this.good,
|
||||||
Key? key,
|
Key? key,
|
||||||
}) : super(key: key);
|
}) : super(key: key);
|
||||||
final GoodRowDao good;
|
final GoodResponse good;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
_GoodEditState createState() => _GoodEditState();
|
_GoodEditState createState() => _GoodEditState();
|
||||||
|
|
@ -44,10 +42,11 @@ class _GoodEditState extends State<GoodEdit> {
|
||||||
super.initState();
|
super.initState();
|
||||||
if (widget.good.categoryId != null) {
|
if (widget.good.categoryId != null) {
|
||||||
parentCategoryId = widget.good.categoryId;
|
parentCategoryId = widget.good.categoryId;
|
||||||
|
parentCategoryName = widget.good.categoryName ?? '';
|
||||||
}
|
}
|
||||||
_controller = TextEditingController(text: widget.good.name);
|
_controller = TextEditingController(text: widget.good.name);
|
||||||
|
|
||||||
getAndStateCategoryName(parentCategoryId);
|
//getAndStateCategoryName(parentCategoryId);
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
|
@ -56,22 +55,22 @@ class _GoodEditState extends State<GoodEdit> {
|
||||||
super.dispose();
|
super.dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> getAndStateCategoryName(int? id) async {
|
// Future<void> getAndStateCategoryName(int? id) async {
|
||||||
String name = '';
|
// String name = '';
|
||||||
if (id == null) {
|
// if (id == null) {
|
||||||
} else if (id == 0) {
|
// } else if (id == 0) {
|
||||||
name = 'Корневая категория';
|
// name = 'Корневая категория';
|
||||||
} else {
|
// } else {
|
||||||
final Category? category = await _dictionaryService.getCategoryById(id);
|
// final Category? category = await _dictionaryService.getCategoryById(id);
|
||||||
if (category != null) {
|
// if (category != null) {
|
||||||
name = category.name;
|
// name = category.name;
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
setState(() {
|
// setState(() {
|
||||||
parentCategoryName = name;
|
// parentCategoryName = name;
|
||||||
parentCategoryId = id;
|
// parentCategoryId = id;
|
||||||
});
|
// });
|
||||||
}
|
// }
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
|
|
@ -166,7 +165,7 @@ class _GoodEditState extends State<GoodEdit> {
|
||||||
final dynamic result =
|
final dynamic result =
|
||||||
await _navigatorService.push(categorySelectViewRoute);
|
await _navigatorService.push(categorySelectViewRoute);
|
||||||
if (result != null) {
|
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/material.dart';
|
||||||
import 'package:flutter_svg/svg.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/category_entity.dart';
|
||||||
import 'package:satu/core/entity/goods_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/models/dictionary/good_row_data.dart';
|
||||||
import 'package:satu/core/redux/actions/sell_actions.dart';
|
import 'package:satu/core/redux/actions/sell_actions.dart';
|
||||||
import 'package:satu/core/services/dictionary_service.dart';
|
import 'package:satu/core/services/dictionary_service.dart';
|
||||||
|
|
@ -25,33 +29,35 @@ class _GoodsDictionaryViewState extends State<GoodsDictionaryView> {
|
||||||
final NavigatorService _navigatorService = locator<NavigatorService>();
|
final NavigatorService _navigatorService = locator<NavigatorService>();
|
||||||
late TextEditingController _searchTextController;
|
late TextEditingController _searchTextController;
|
||||||
final FocusNode _searchFocusNode = FocusNode();
|
final FocusNode _searchFocusNode = FocusNode();
|
||||||
|
static const _pageSize = 20;
|
||||||
|
String query = '';
|
||||||
|
Timer? _debounce;
|
||||||
|
|
||||||
late List<Good> _goods = [];
|
final PagingController<int, GoodResponse> _pagingController =
|
||||||
late List<Category> _categories = [];
|
PagingController(firstPageKey: 1);
|
||||||
late List<GoodRowDao> items = [];
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
_searchTextController = TextEditingController();
|
_searchTextController = TextEditingController();
|
||||||
_searchTextController.addListener(() {
|
_searchTextController.addListener(() {
|
||||||
if (_searchTextController.text.isNotEmpty) {
|
setState(() {
|
||||||
searchByField(_searchTextController.text);
|
query = _searchTextController.text;
|
||||||
} else {
|
});
|
||||||
reset();
|
if (_debounce?.isActive ?? false) _debounce?.cancel();
|
||||||
}
|
_debounce = Timer(const Duration(milliseconds: 500), () {
|
||||||
|
_pagingController.refresh();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
_pagingController.addPageRequestListener((pageKey) {
|
||||||
|
_fetchData(pageKey, _pageSize, query);
|
||||||
});
|
});
|
||||||
initQuery();
|
|
||||||
super.initState();
|
super.initState();
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> initQuery() async {
|
|
||||||
_goods = await _dictionaryService.getGoodsByNameOrEan('');
|
|
||||||
_categories = await _dictionaryService.getCategoriesAll();
|
|
||||||
searchByField('');
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void dispose() {
|
void dispose() {
|
||||||
|
_debounce?.cancel();
|
||||||
|
_pagingController.dispose();
|
||||||
_searchTextController.dispose();
|
_searchTextController.dispose();
|
||||||
_searchFocusNode.dispose();
|
_searchFocusNode.dispose();
|
||||||
super.dispose();
|
super.dispose();
|
||||||
|
|
@ -94,37 +100,40 @@ class _GoodsDictionaryViewState extends State<GoodsDictionaryView> {
|
||||||
),
|
),
|
||||||
const ProductsTitleBarBar(title: 'Список товаров'),
|
const ProductsTitleBarBar(title: 'Список товаров'),
|
||||||
Expanded(
|
Expanded(
|
||||||
child: ListView.separated(
|
child: PagedListView<int, GoodResponse>.separated(
|
||||||
physics: const BouncingScrollPhysics(),
|
physics: const BouncingScrollPhysics(),
|
||||||
itemCount: items.length,
|
separatorBuilder: (BuildContext context, int index) {
|
||||||
itemBuilder: (BuildContext context, int index) {
|
return const Divider(
|
||||||
final GoodRowDao good = items[index];
|
height: 1.0,
|
||||||
return DictionaryTile(
|
color: disableColor,
|
||||||
onPress: () {
|
);
|
||||||
locator<NavigatorService>()
|
},
|
||||||
.push(goodsEditRoute, arguments: good);
|
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(
|
floatingActionButton: FloatingActionButton(
|
||||||
elevation: 2,
|
elevation: 2,
|
||||||
onPressed: () => locator<NavigatorService>()
|
onPressed: () =>
|
||||||
.push(goodsEditRoute, arguments: GoodRowDao('', '')),
|
locator<NavigatorService>()
|
||||||
|
.push(goodsEditRoute, arguments: GoodRowDao('', '')),
|
||||||
child: const Icon(
|
child: const Icon(
|
||||||
Icons.add_rounded,
|
Icons.add_rounded,
|
||||||
size: 34.0,
|
size: 34.0,
|
||||||
|
|
@ -136,30 +145,18 @@ class _GoodsDictionaryViewState extends State<GoodsDictionaryView> {
|
||||||
|
|
||||||
void reset() {
|
void reset() {
|
||||||
_searchTextController.clear();
|
_searchTextController.clear();
|
||||||
searchByField('');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> searchByField(String query) async {
|
Future<void> _fetchData(int pageKey, int perPage, String? query) async {
|
||||||
log.i(query);
|
final List<GoodResponse> newItems = await _dictionaryService.getGoods(
|
||||||
final List<GoodRowDao> list = [];
|
page: pageKey, query: query, perpage: perPage);
|
||||||
final Iterable<Good> filtered = query == ''
|
|
||||||
? _goods
|
final isLastPage = newItems.length < _pageSize;
|
||||||
: _goods.where((element) =>
|
if (isLastPage) {
|
||||||
element.name.toLowerCase().contains(query.toLowerCase()) ||
|
_pagingController.appendLastPage(newItems);
|
||||||
(element.ean != null &&
|
} else {
|
||||||
element.ean!.contains(query.toLowerCase())));
|
final nextPageKey = pageKey + 1;
|
||||||
filtered.forEach((element) {
|
_pagingController.appendPage(newItems, nextPageKey);
|
||||||
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;
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,3 @@
|
||||||
import 'dart:ui';
|
|
||||||
|
|
||||||
import 'package:flutter/services.dart';
|
|
||||||
import 'package:flutter_redux/flutter_redux.dart';
|
import 'package:flutter_redux/flutter_redux.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_screenutil/flutter_screenutil.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/services/navigator_service.dart';
|
||||||
import 'package:satu/core/utils/locator.dart';
|
import 'package:satu/core/utils/locator.dart';
|
||||||
import 'package:satu/routes/route_names.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/shared/ui_helpers.dart';
|
||||||
import 'package:satu/widgets/buttons/busy_button.dart';
|
import 'package:satu/widgets/buttons/busy_button.dart';
|
||||||
import 'package:satu/widgets/fields/input_field.dart';
|
import 'package:satu/widgets/fields/input_field.dart';
|
||||||
|
|
@ -52,57 +48,55 @@ class _LoginViewState extends State<LoginView> {
|
||||||
return StoreConnector<AppState, UserState>(
|
return StoreConnector<AppState, UserState>(
|
||||||
converter: (store) => store.state.userState!,
|
converter: (store) => store.state.userState!,
|
||||||
builder: (context, vm) {
|
builder: (context, vm) {
|
||||||
return Scaffold(
|
return Scaffold(body: LayoutBuilder(
|
||||||
body: LayoutBuilder(
|
builder: (context, constraints) {
|
||||||
builder: (context, constraints) {
|
return SingleChildScrollView(
|
||||||
return SingleChildScrollView(
|
child: ConstrainedBox(
|
||||||
child: ConstrainedBox(
|
constraints: BoxConstraints(minHeight: constraints.maxHeight),
|
||||||
constraints: BoxConstraints(minHeight: constraints.maxHeight),
|
child: Column(
|
||||||
child: Column(
|
mainAxisSize: MainAxisSize.max,
|
||||||
mainAxisSize: MainAxisSize.max,
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
crossAxisAlignment: CrossAxisAlignment.center,
|
||||||
crossAxisAlignment: CrossAxisAlignment.center,
|
children: <Widget>[
|
||||||
children: <Widget>[
|
const LogoSatu(),
|
||||||
const LogoSatu(),
|
InputField(
|
||||||
InputField(
|
placeholder: 'Введите почту',
|
||||||
placeholder: 'Введите почту',
|
controller: emailController,
|
||||||
controller: emailController,
|
textInputType: TextInputType.emailAddress,
|
||||||
textInputType: TextInputType.emailAddress,
|
nextFocusNode: passwordNode,
|
||||||
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,
|
|
||||||
)
|
|
||||||
],
|
|
||||||
),
|
),
|
||||||
),
|
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 кода');
|
_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 {
|
class LoginModel {
|
||||||
|
LoginModel(
|
||||||
|
{required this.authType, required this.login, required this.password});
|
||||||
|
|
||||||
final String authType;
|
final String authType;
|
||||||
final String login;
|
final String login;
|
||||||
final String password;
|
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/analytics/analytics_view.dart';
|
||||||
import 'package:satu/views/dictionaries/category/category_view.dart';
|
import 'package:satu/views/dictionaries/category/category_view.dart';
|
||||||
import 'package:satu/views/dictionaries/goods/goods_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/settings/setting_view.dart';
|
||||||
import 'package:satu/views/work/work_view.dart';
|
import 'package:satu/views/work/work_view.dart';
|
||||||
import 'package:satu/widgets/drawer/app_drawer.dart';
|
import 'package:satu/widgets/drawer/app_drawer.dart';
|
||||||
|
|
||||||
|
import '../dictionaries/contragents/contragents_view.dart';
|
||||||
|
|
||||||
class MainView extends StatefulWidget {
|
class MainView extends StatefulWidget {
|
||||||
@override
|
@override
|
||||||
_MainViewState createState() => _MainViewState();
|
_MainViewState createState() => _MainViewState();
|
||||||
|
|
@ -25,6 +26,7 @@ class _MainViewState extends State<MainView> {
|
||||||
final _settingsView = SettingsView();
|
final _settingsView = SettingsView();
|
||||||
final _categoryDictView = CategoryDictionaryView();
|
final _categoryDictView = CategoryDictionaryView();
|
||||||
final _goodDictView = GoodsDictionaryView();
|
final _goodDictView = GoodsDictionaryView();
|
||||||
|
final _contragentDictView = ContragentsDictionaryView();
|
||||||
final _analyticsView = const AnalyticsView();
|
final _analyticsView = const AnalyticsView();
|
||||||
|
|
||||||
Widget _body(Type viewClass) {
|
Widget _body(Type viewClass) {
|
||||||
|
|
@ -40,6 +42,9 @@ class _MainViewState extends State<MainView> {
|
||||||
if(viewClass == GoodsDictionaryView) {
|
if(viewClass == GoodsDictionaryView) {
|
||||||
return _goodDictView;
|
return _goodDictView;
|
||||||
}
|
}
|
||||||
|
if(viewClass == ContragentsDictionaryView) {
|
||||||
|
return _contragentDictView;
|
||||||
|
}
|
||||||
if(viewClass == AnalyticsView) {
|
if(viewClass == AnalyticsView) {
|
||||||
return _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.dart';
|
||||||
// import 'package:bluetooth_print/bluetooth_print_model.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:esc_pos_bluetooth/esc_pos_bluetooth.dart';
|
||||||
import 'package:flutter/material.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/services/navigator_service.dart';
|
||||||
import 'package:satu/core/utils/locator.dart';
|
import 'package:satu/core/utils/locator.dart';
|
||||||
import 'package:satu/routes/route_names.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_app_bar.dart';
|
||||||
import 'package:satu/widgets/bar/products_title_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_redux/flutter_redux.dart';
|
||||||
import 'package:flutter/material.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/actions/user_actions.dart';
|
||||||
import 'package:satu/core/redux/state/user_state.dart';
|
import 'package:satu/core/redux/state/user_state.dart';
|
||||||
import 'package:satu/core/redux/store.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/services/navigator_service.dart';
|
||||||
import 'package:satu/core/utils/locator.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/app_colors.dart';
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -19,7 +16,6 @@ class StartUpView extends StatefulWidget {
|
||||||
|
|
||||||
class _StartUpViewState extends State<StartUpView> {
|
class _StartUpViewState extends State<StartUpView> {
|
||||||
final NavigatorService _navigation = locator<NavigatorService>();
|
final NavigatorService _navigation = locator<NavigatorService>();
|
||||||
final ApiService _api = locator<ApiService>();
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,4 @@
|
||||||
import 'package:flutter/material.dart';
|
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';
|
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/core/utils/locator.dart';
|
||||||
import 'package:satu/routes/route_names.dart';
|
import 'package:satu/routes/route_names.dart';
|
||||||
import 'package:satu/shared/app_colors.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 {
|
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
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
|
|
|
||||||
|
|
@ -2,12 +2,12 @@ import 'package:flutter/material.dart';
|
||||||
|
|
||||||
class CustomField extends StatelessWidget {
|
class CustomField extends StatelessWidget {
|
||||||
|
|
||||||
|
CustomField({@required this.hintText, @required this.iconData, this.label});
|
||||||
|
|
||||||
final String? hintText;
|
final String? hintText;
|
||||||
final IconData? iconData;
|
final IconData? iconData;
|
||||||
final String? label;
|
final String? label;
|
||||||
|
|
||||||
CustomField({@required this.hintText, @required this.iconData, this.label});
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Container(
|
return Container(
|
||||||
|
|
|
||||||
|
|
@ -20,11 +20,11 @@ Future dialog(BuildContext cont) async {
|
||||||
const Expanded(
|
const Expanded(
|
||||||
flex: 1,
|
flex: 1,
|
||||||
child: Text(
|
child: Text(
|
||||||
"Sample type",
|
'Sample type',
|
||||||
style: TextStyle(fontWeight: FontWeight.w700),
|
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/material.dart';
|
||||||
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
||||||
import 'package:satu/core/models/dialog_models.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/views/work/views/add_by_barcode/add_by_barcode_view.dart';
|
||||||
import 'package:satu/widgets/ui/product_title_widget.dart';
|
import 'package:satu/widgets/ui/product_title_widget.dart';
|
||||||
|
|
||||||
import 'dialog_edit_product.dart';
|
|
||||||
|
|
||||||
class ProductListItem extends StatefulWidget {
|
class ProductListItem extends StatefulWidget {
|
||||||
const ProductListItem(
|
const ProductListItem(
|
||||||
|
|
|
||||||
|
|
@ -2,67 +2,61 @@ import 'package:flutter/material.dart';
|
||||||
|
|
||||||
class TransactionItem extends StatelessWidget {
|
class TransactionItem extends StatelessWidget {
|
||||||
|
|
||||||
|
TransactionItem(
|
||||||
|
{required this.fullName,
|
||||||
|
required this.status,
|
||||||
|
required this.amount,
|
||||||
|
required this.received});
|
||||||
final String fullName;
|
final String fullName;
|
||||||
final String status;
|
final String status;
|
||||||
final String amount;
|
final String amount;
|
||||||
final bool received;
|
final bool received;
|
||||||
|
|
||||||
TransactionItem({required this.fullName, required this.status, required this.amount, required this.received});
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Container(
|
return Container(
|
||||||
margin: EdgeInsets.symmetric(vertical: 8),
|
margin: EdgeInsets.symmetric(vertical: 8),
|
||||||
child: Row(
|
child: Row(children: [
|
||||||
children: [
|
Container(
|
||||||
|
width: 16,
|
||||||
Container(
|
height: 50,
|
||||||
width: 16,
|
//margin: EdgeInsets.only(right: 16),
|
||||||
height: 50,
|
// child: Icon(
|
||||||
//margin: EdgeInsets.only(right: 16),
|
// Icons.memory
|
||||||
// child: Icon(
|
// ),
|
||||||
// Icons.memory
|
),
|
||||||
// ),
|
Expanded(
|
||||||
),
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
Expanded(
|
children: [
|
||||||
child: Column(
|
Text(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
fullName,
|
||||||
children: [
|
style: TextStyle(
|
||||||
|
//color: kPrimaryColor,
|
||||||
Text(
|
fontSize: 16,
|
||||||
fullName,
|
fontWeight: FontWeight.bold,
|
||||||
style: TextStyle(
|
),
|
||||||
//color: kPrimaryColor,
|
|
||||||
fontSize: 16,
|
|
||||||
fontWeight: FontWeight.bold,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
|
|
||||||
Text(
|
|
||||||
status,
|
|
||||||
style: TextStyle(
|
|
||||||
//color: kGreyColor,
|
|
||||||
fontSize: 12,
|
|
||||||
fontWeight: FontWeight.w500,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
|
|
||||||
],
|
|
||||||
),
|
),
|
||||||
),
|
Text(
|
||||||
|
status,
|
||||||
Text(
|
style: TextStyle(
|
||||||
(received ? "+" : "-") + r" $ " + amount + " KZT",
|
//color: kGreyColor,
|
||||||
style: TextStyle(
|
fontSize: 12,
|
||||||
color: received ? Colors.green : Colors.red,
|
fontWeight: FontWeight.w500,
|
||||||
fontSize: 16,
|
),
|
||||||
fontWeight: FontWeight.bold,
|
|
||||||
),
|
),
|
||||||
),
|
],
|
||||||
|
),
|
||||||
]
|
),
|
||||||
),
|
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/material.dart';
|
||||||
import 'package:flutter_redux/flutter_redux.dart';
|
import 'package:flutter_redux/flutter_redux.dart';
|
||||||
import 'package:grouped_list/grouped_list.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/models/flow/dao/transaction_dao.dart';
|
||||||
import 'package:satu/core/redux/actions/journal_actions.dart';
|
import 'package:satu/core/redux/actions/journal_actions.dart';
|
||||||
import 'package:satu/core/redux/state/journal_state.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/bar/products_app_bar.dart';
|
||||||
import 'package:satu/widgets/buttons/option_pill.dart';
|
import 'package:satu/widgets/buttons/option_pill.dart';
|
||||||
import 'component/journal_list_tile.dart';
|
import 'component/journal_list_tile.dart';
|
||||||
import 'component/transaction_item.dart';
|
|
||||||
|
|
||||||
class JournalView extends StatefulWidget {
|
class JournalView extends StatefulWidget {
|
||||||
@override
|
@override
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,3 @@
|
||||||
import 'package:flutter/cupertino.dart';
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_redux/flutter_redux.dart';
|
import 'package:flutter_redux/flutter_redux.dart';
|
||||||
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
||||||
|
|
@ -138,13 +137,13 @@ class SellView extends StatelessWidget {
|
||||||
final dynamic result =
|
final dynamic result =
|
||||||
await _nav.push(addByBarcodeViewRoute);
|
await _nav.push(addByBarcodeViewRoute);
|
||||||
if (result != null) {
|
if (result != null) {
|
||||||
final List<Good> goods =
|
// final List<Good> goods =
|
||||||
await locator<DictionaryService>()
|
// await locator<DictionaryService>()
|
||||||
.getGoodsByEan(result as String);
|
// .getGoodsByEan(result as String);
|
||||||
if (goods.isNotEmpty) {
|
// if (goods.isNotEmpty) {
|
||||||
Redux.store
|
// Redux.store
|
||||||
?.dispatch(addSellItem(good: goods.first));
|
// ?.dispatch(addSellItem(good: goods.first));
|
||||||
}
|
// }
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
child: Icon(Icons.qr_code_rounded,
|
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:flutter/material.dart';
|
||||||
import 'package:satu/core/services/navigator_service.dart';
|
import 'package:satu/core/services/navigator_service.dart';
|
||||||
import 'package:satu/core/utils/locator.dart';
|
import 'package:satu/core/utils/locator.dart';
|
||||||
|
|
|
||||||
|
|
@ -26,25 +26,21 @@ class _AddProductViewState extends State<AddProductView> {
|
||||||
late TextEditingController _searchTextController;
|
late TextEditingController _searchTextController;
|
||||||
final FocusNode _searchFocusNode = new FocusNode();
|
final FocusNode _searchFocusNode = new FocusNode();
|
||||||
|
|
||||||
|
|
||||||
List<Category>? _history;
|
List<Category>? _history;
|
||||||
List<Category>? _categories;
|
List<Category>? _categories;
|
||||||
List<Good>? _goods;
|
List<Good>? _goods;
|
||||||
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
_searchTextController = TextEditingController();
|
_searchTextController = TextEditingController();
|
||||||
_searchTextController.addListener(() {
|
_searchTextController.addListener(() {
|
||||||
if(_searchTextController.text.isNotEmpty){
|
if (_searchTextController.text.isNotEmpty) {
|
||||||
searchByField(_searchTextController.text);
|
searchByField(_searchTextController.text);
|
||||||
} else {
|
} else {
|
||||||
reset();
|
reset();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
_history = [Category()
|
_history = [Category()..id = 0];
|
||||||
..id = 0
|
|
||||||
];
|
|
||||||
_categories = [];
|
_categories = [];
|
||||||
_goods = [];
|
_goods = [];
|
||||||
super.initState();
|
super.initState();
|
||||||
|
|
@ -63,15 +59,21 @@ class _AddProductViewState extends State<AddProductView> {
|
||||||
int catSize = _categories?.length ?? 0;
|
int catSize = _categories?.length ?? 0;
|
||||||
int goodSize = _goods?.length ?? 0;
|
int goodSize = _goods?.length ?? 0;
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
appBar: ProductsAppBar( title: 'Категория',),
|
appBar: ProductsAppBar(
|
||||||
|
title: 'Категория',
|
||||||
|
),
|
||||||
body: Column(
|
body: Column(
|
||||||
children: [
|
children: [
|
||||||
InputField(placeholder: 'Поиск по наименованию или коду товара',
|
InputField(
|
||||||
|
placeholder: 'Поиск по наименованию или коду товара',
|
||||||
search: true,
|
search: true,
|
||||||
controller: _searchTextController,
|
controller: _searchTextController,
|
||||||
fieldFocusNode: _searchFocusNode,),
|
fieldFocusNode: _searchFocusNode,
|
||||||
|
),
|
||||||
verticalSpaceTiny,
|
verticalSpaceTiny,
|
||||||
ProductsTitleBarBar(title: goodSize > 0 ? 'Выберите товар' : 'Выберите категорию',),
|
ProductsTitleBarBar(
|
||||||
|
title: goodSize > 0 ? 'Выберите товар' : 'Выберите категорию',
|
||||||
|
),
|
||||||
Expanded(
|
Expanded(
|
||||||
child: ListView.separated(
|
child: ListView.separated(
|
||||||
physics: BouncingScrollPhysics(),
|
physics: BouncingScrollPhysics(),
|
||||||
|
|
@ -94,14 +96,17 @@ class _AddProductViewState extends State<AddProductView> {
|
||||||
categoryName: _history?.last.name,
|
categoryName: _history?.last.name,
|
||||||
onPress: () {
|
onPress: () {
|
||||||
onGoodPress(good);
|
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() {
|
void reset() {
|
||||||
_history = [Category()
|
_history = [Category()..id = 0];
|
||||||
..id = 0
|
navigateCategory(0);
|
||||||
];
|
_searchTextController.clear();
|
||||||
navigateCategory(0);
|
}
|
||||||
_searchTextController.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
void navigateCategory(int categoryId) async {
|
void navigateCategory(int categoryId) async {
|
||||||
List<Category> categories = await _dictionaryService.getCategoryByParentId(categoryId);
|
List<Category> categories =
|
||||||
List<Good> goods = await _dictionaryService.getGoodsByCategoryId(categoryId);
|
await _dictionaryService.getCategoryByParentId(categoryId);
|
||||||
|
List<Good> goods =
|
||||||
|
await _dictionaryService.getGoodsByCategoryId(categoryId);
|
||||||
setState(() {
|
setState(() {
|
||||||
_categories = categories;
|
_categories = categories;
|
||||||
_goods = goods;
|
_goods = goods;
|
||||||
|
|
@ -142,5 +147,4 @@ class _AddProductViewState extends State<AddProductView> {
|
||||||
_goods = goods;
|
_goods = goods;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,15 +1,12 @@
|
||||||
import 'package:flutter/cupertino.dart';
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:satu/shared/app_colors.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 {
|
class AddCategoryListItem extends StatelessWidget {
|
||||||
final String name;
|
|
||||||
final Function? onPress;
|
|
||||||
|
|
||||||
const AddCategoryListItem({Key? key, this.name = '', this.onPress})
|
const AddCategoryListItem({Key? key, this.name = '', this.onPress})
|
||||||
: super(key: key);
|
: super(key: key);
|
||||||
|
final String name;
|
||||||
|
final Function? onPress;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,3 @@
|
||||||
import 'package:flutter/cupertino.dart';
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
||||||
import 'package:satu/shared/app_colors.dart';
|
import 'package:satu/shared/app_colors.dart';
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,5 @@
|
||||||
import 'package:flutter/cupertino.dart';
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:satu/shared/app_colors.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 {
|
class ContragentListItem extends StatelessWidget {
|
||||||
const ContragentListItem({Key? key, this.name, this.onPress})
|
const ContragentListItem({Key? key, this.name, this.onPress})
|
||||||
|
|
|
||||||
|
|
@ -1,14 +1,11 @@
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:satu/core/entity/category_entity.dart';
|
import 'package:satu/core/entity/category_entity.dart';
|
||||||
import 'package:satu/core/entity/goods_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/dictionary_service.dart';
|
||||||
import 'package:satu/core/services/navigator_service.dart';
|
import 'package:satu/core/services/navigator_service.dart';
|
||||||
import 'package:satu/core/utils/locator.dart';
|
import 'package:satu/core/utils/locator.dart';
|
||||||
import 'package:satu/shared/app_colors.dart';
|
import 'package:satu/shared/app_colors.dart';
|
||||||
import 'package:satu/shared/ui_helpers.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_app_bar.dart';
|
||||||
import 'package:satu/widgets/bar/products_title_bar.dart';
|
import 'package:satu/widgets/bar/products_title_bar.dart';
|
||||||
import 'package:satu/widgets/fields/input_field.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/core/utils/utils_parse.dart';
|
||||||
import 'package:satu/shared/app_colors.dart';
|
import 'package:satu/shared/app_colors.dart';
|
||||||
import 'package:satu/shared/ui_helpers.dart';
|
import 'package:satu/shared/ui_helpers.dart';
|
||||||
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
|
||||||
|
|
||||||
class CombineDock extends StatelessWidget {
|
class CombineDock extends StatelessWidget {
|
||||||
const CombineDock({
|
const CombineDock({
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,5 @@
|
||||||
import 'package:flutter/cupertino.dart';
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_redux/flutter_redux.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/state/sell_state.dart';
|
||||||
import 'package:satu/core/redux/store.dart';
|
import 'package:satu/core/redux/store.dart';
|
||||||
import 'package:satu/core/services/navigator_service.dart';
|
import 'package:satu/core/services/navigator_service.dart';
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,7 @@
|
||||||
import 'dart:convert';
|
import 'dart:convert';
|
||||||
import 'dart:io';
|
|
||||||
|
|
||||||
import 'package:esc_pos_bluetooth/esc_pos_bluetooth.dart';
|
import 'package:esc_pos_bluetooth/esc_pos_bluetooth.dart';
|
||||||
import 'package:flutter/material.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/entity/transaction_entity.dart';
|
||||||
import 'package:satu/core/models/dialog_models.dart';
|
import 'package:satu/core/models/dialog_models.dart';
|
||||||
import 'package:satu/core/models/entity_data/transaction_data.dart';
|
import 'package:satu/core/models/entity_data/transaction_data.dart';
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,7 @@
|
||||||
import 'package:flutter/material.dart';
|
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/actions/sell_actions.dart';
|
||||||
import 'package:satu/core/redux/store.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/buy_view.dart';
|
||||||
import 'package:satu/views/work/tabs/journal_view.dart';
|
import 'package:satu/views/work/tabs/journal_view.dart';
|
||||||
import 'package:satu/views/work/tabs/sell_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/services/navigator_service.dart';
|
||||||
import 'package:satu/core/utils/locator.dart';
|
import 'package:satu/core/utils/locator.dart';
|
||||||
import 'package:satu/shared/app_colors.dart';
|
import 'package:satu/shared/app_colors.dart';
|
||||||
import 'package:satu/widgets/bar/products_header_bar.dart';
|
|
||||||
|
|
||||||
class ProductsAppBar extends StatelessWidget implements PreferredSizeWidget {
|
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(
|
const ProductsAppBar(
|
||||||
{Key? key,
|
{Key? key,
|
||||||
|
|
@ -23,6 +15,13 @@ class ProductsAppBar extends StatelessWidget implements PreferredSizeWidget {
|
||||||
this.drawerShow = false,
|
this.drawerShow = false,
|
||||||
this.backgroundColor = Colors.transparent})
|
this.backgroundColor = Colors.transparent})
|
||||||
: super(key: key);
|
: 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
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,5 @@
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
|
||||||
import 'package:satu/shared/app_colors.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 {
|
class ProductHeaderBar extends StatelessWidget {
|
||||||
const ProductHeaderBar({required this.count, required this.sum , Key? key})
|
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:auto_size_text/auto_size_text.dart';
|
||||||
import 'package:flutter/material.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
|
/// A button that shows a busy indicator in place of title
|
||||||
class AmanIconButton extends StatefulWidget {
|
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/material.dart';
|
||||||
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
||||||
import 'package:satu/shared/app_colors.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
|
/// A button that shows a busy indicator in place of title
|
||||||
class BusyButton extends StatefulWidget {
|
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 bool busy;
|
||||||
final String title;
|
final String title;
|
||||||
final Function onPressed;
|
final Function onPressed;
|
||||||
|
|
@ -13,15 +21,6 @@ class BusyButton extends StatefulWidget {
|
||||||
final bool isCancel;
|
final bool isCancel;
|
||||||
final bool isDanger;
|
final bool isDanger;
|
||||||
|
|
||||||
const BusyButton({
|
|
||||||
required this.title,
|
|
||||||
this.busy = false,
|
|
||||||
required this.onPressed,
|
|
||||||
this.enabled = true,
|
|
||||||
this.isCancel = false,
|
|
||||||
this.isDanger = false,
|
|
||||||
});
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
_BusyButtonState createState() => _BusyButtonState();
|
_BusyButtonState createState() => _BusyButtonState();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,21 +1,17 @@
|
||||||
import 'package:flutter/cupertino.dart';
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter/services.dart';
|
|
||||||
import 'package:flutter_screenutil/flutter_screenutil.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/models/dialog_models.dart';
|
||||||
import 'package:satu/core/services/dialog_service.dart';
|
import 'package:satu/core/services/dialog_service.dart';
|
||||||
import 'package:satu/core/utils/locator.dart';
|
import 'package:satu/core/utils/locator.dart';
|
||||||
import 'package:satu/shared/app_colors.dart';
|
import 'package:satu/shared/app_colors.dart';
|
||||||
import 'package:satu/shared/ui_helpers.dart';
|
import 'package:satu/shared/ui_helpers.dart';
|
||||||
import 'package:satu/widgets/buttons/busy_button.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';
|
import 'package:satu/widgets/fields/input_field_rounded.dart';
|
||||||
|
|
||||||
class DialogManager extends StatefulWidget {
|
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();
|
_DialogManagerState createState() => _DialogManagerState();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,12 @@
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
class DialogModalSelect extends StatefulWidget {
|
class DialogModalSelect extends StatefulWidget {
|
||||||
final String? title;
|
|
||||||
final String? descriptions;
|
|
||||||
final String? text;
|
|
||||||
|
|
||||||
const DialogModalSelect({Key? key, this.title, this.descriptions, this.text})
|
const DialogModalSelect({Key? key, this.title, this.descriptions, this.text})
|
||||||
: super(key: key);
|
: super(key: key);
|
||||||
|
final String? title;
|
||||||
|
final String? descriptions;
|
||||||
|
final String? text;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
_DialogModalSelectState createState() => _DialogModalSelectState();
|
_DialogModalSelectState createState() => _DialogModalSelectState();
|
||||||
|
|
@ -86,7 +86,7 @@ class _DialogModalSelectState extends State<DialogModalSelect> {
|
||||||
radius: avatarRadius,
|
radius: avatarRadius,
|
||||||
child: ClipRRect(
|
child: ClipRRect(
|
||||||
borderRadius: BorderRadius.all(Radius.circular(avatarRadius)),
|
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/material.dart';
|
||||||
import 'package:flutter_redux/flutter_redux.dart';
|
import 'package:flutter_redux/flutter_redux.dart';
|
||||||
import 'package:flutter_screenutil/flutter_screenutil.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/shared/ui_helpers.dart';
|
||||||
import 'package:satu/views/analytics/analytics_view.dart';
|
import 'package:satu/views/analytics/analytics_view.dart';
|
||||||
import 'package:satu/views/dictionaries/category/category_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/dictionaries/goods/goods_view.dart';
|
||||||
import 'package:satu/views/settings/setting_view.dart';
|
import 'package:satu/views/settings/setting_view.dart';
|
||||||
import 'package:satu/views/work/work_view.dart';
|
import 'package:satu/views/work/work_view.dart';
|
||||||
|
|
@ -28,62 +28,95 @@ class AppDrawer extends StatelessWidget {
|
||||||
_createHeader(),
|
_createHeader(),
|
||||||
_createDrawerSectionTitle(text: 'ОСНОВНОЙ РАЗДЕЛ'),
|
_createDrawerSectionTitle(text: 'ОСНОВНОЙ РАЗДЕЛ'),
|
||||||
_createDrawerItem(
|
_createDrawerItem(
|
||||||
svgFile: 'sell',
|
svgFile: 'sell',
|
||||||
text: 'Касса',
|
text: 'Касса',
|
||||||
onTap: () {
|
onTap: () {
|
||||||
Navigator.of(context).pop();
|
Navigator.of(context).pop();
|
||||||
Redux.store!.dispatch(navigateDrawer(WorkView));
|
Redux.store!.dispatch(navigateDrawer(WorkView));
|
||||||
},),
|
},
|
||||||
|
),
|
||||||
_createDrawerItem(
|
_createDrawerItem(
|
||||||
svgFile: 'analytics',
|
icon: Icons.analytics,
|
||||||
text: 'Аналитика',
|
text: 'Аналитика',
|
||||||
onTap: () {
|
onTap: () {
|
||||||
Navigator.of(context).pop();
|
Navigator.of(context).pop();
|
||||||
Redux.store!.dispatch(navigateDrawer(AnalyticsView));
|
Redux.store!.dispatch(navigateDrawer(AnalyticsView));
|
||||||
},),
|
},
|
||||||
|
),
|
||||||
_createDrawerItem(
|
_createDrawerItem(
|
||||||
svgFile: 'inventarization',
|
icon: Icons.archive,
|
||||||
text: 'Инвентаризация',
|
text: 'Остатки',
|
||||||
disable: true),
|
onTap: () {
|
||||||
|
Navigator.of(context).pop();
|
||||||
|
Redux.store!.dispatch(navigateDrawer(AnalyticsView));
|
||||||
|
},
|
||||||
|
disable: true,
|
||||||
|
),
|
||||||
|
_createDrawerItem(
|
||||||
|
svgFile: 'inventarization',
|
||||||
|
text: 'Инвентаризация',
|
||||||
|
disable: true,
|
||||||
|
),
|
||||||
_createDrawerSectionTitle(text: 'СПРАВОЧНИКИ'),
|
_createDrawerSectionTitle(text: 'СПРАВОЧНИКИ'),
|
||||||
_createDrawerItem(
|
_createDrawerItem(
|
||||||
svgFile: 'categories',
|
svgFile: 'categories',
|
||||||
text: 'Категории',
|
text: 'Категории',
|
||||||
onTap: () {
|
onTap: () {
|
||||||
Navigator.of(context).pop();
|
Navigator.of(context).pop();
|
||||||
Redux.store!.dispatch(navigateDrawer(CategoryDictionaryView));
|
Redux.store!.dispatch(navigateDrawer(CategoryDictionaryView));
|
||||||
}),
|
},
|
||||||
|
),
|
||||||
_createDrawerItem(
|
_createDrawerItem(
|
||||||
svgFile: 'goods',
|
svgFile: 'goods',
|
||||||
text: 'Товары',
|
text: 'Товары',
|
||||||
onTap: () {
|
onTap: () {
|
||||||
Navigator.of(context).pop();
|
Navigator.of(context).pop();
|
||||||
Redux.store!.dispatch(navigateDrawer(GoodsDictionaryView));
|
Redux.store!.dispatch(navigateDrawer(GoodsDictionaryView));
|
||||||
}),
|
},
|
||||||
|
),
|
||||||
_createDrawerItem(
|
_createDrawerItem(
|
||||||
svgFile: 'contragents', text: 'Контрагенты', disable: true),
|
svgFile: 'contragents',
|
||||||
|
text: 'Контрагенты',
|
||||||
|
onTap: () {
|
||||||
|
Navigator.of(context).pop();
|
||||||
|
Redux.store!.dispatch(
|
||||||
|
navigateDrawer(ContragentsDictionaryView)
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
_createDrawerSectionTitle(text: 'ИНФОРМАЦИЯ'),
|
_createDrawerSectionTitle(text: 'ИНФОРМАЦИЯ'),
|
||||||
_createDrawerItem(
|
_createDrawerItem(
|
||||||
svgFile: 'question', text: 'Справочник', disable: true),
|
svgFile: 'question',
|
||||||
|
text: 'Справочник',
|
||||||
|
disable: true,
|
||||||
|
),
|
||||||
_createDrawerSectionTitle(text: 'ПРОЧЕЕ'),
|
_createDrawerSectionTitle(text: 'ПРОЧЕЕ'),
|
||||||
_createDrawerItem(
|
_createDrawerItem(
|
||||||
svgFile: 'settings',
|
svgFile: 'settings',
|
||||||
text: 'Настройки',
|
text: 'Настройки',
|
||||||
onTap: () {
|
onTap: () {
|
||||||
Navigator.of(context).pop();
|
Navigator.of(context).pop();
|
||||||
Redux.store!.dispatch(navigateDrawer(SettingsView));
|
Redux.store!.dispatch(navigateDrawer(SettingsView));
|
||||||
}),
|
},
|
||||||
|
),
|
||||||
_createDrawerItem(
|
_createDrawerItem(
|
||||||
svgFile: 'global', text: 'Перейти на сайт', disable: true),
|
svgFile: 'global',
|
||||||
|
text: 'Перейти на сайт',
|
||||||
|
disable: true,
|
||||||
|
),
|
||||||
_createDrawerItem(
|
_createDrawerItem(
|
||||||
svgFile: 'bug', text: 'Сообщить об ошибке', disable: true),
|
svgFile: 'bug',
|
||||||
|
text: 'Сообщить об ошибке',
|
||||||
|
disable: true,
|
||||||
|
),
|
||||||
_createDrawerItem(
|
_createDrawerItem(
|
||||||
svgFile: 'logout',
|
svgFile: 'logout',
|
||||||
text: 'Выйти из аккаунта',
|
text: 'Выйти из аккаунта',
|
||||||
isDanger: true,
|
isDanger: true,
|
||||||
onTap: () async {
|
onTap: () async {
|
||||||
Redux.store!.dispatch(logout);
|
Redux.store!.dispatch(logout);
|
||||||
}),
|
},
|
||||||
|
),
|
||||||
_createDrawerSectionTitle(text: ''),
|
_createDrawerSectionTitle(text: ''),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
|
@ -95,44 +128,60 @@ class AppDrawer extends StatelessWidget {
|
||||||
return SizedBox(
|
return SizedBox(
|
||||||
height: 180.h,
|
height: 180.h,
|
||||||
child: DrawerHeader(
|
child: DrawerHeader(
|
||||||
margin: EdgeInsets.zero,
|
margin: EdgeInsets.zero,
|
||||||
padding: EdgeInsets.zero,
|
padding: EdgeInsets.zero,
|
||||||
decoration: const BoxDecoration(
|
decoration: const BoxDecoration(
|
||||||
image: DecorationImage(
|
image: DecorationImage(
|
||||||
fit: BoxFit.cover,
|
fit: BoxFit.cover,
|
||||||
image: AssetImage('assets/images/drawer/background.png'))),
|
image: AssetImage('assets/images/drawer/background.png'),
|
||||||
child: Stack(children: <Widget>[
|
),
|
||||||
|
),
|
||||||
|
child: Stack(
|
||||||
|
children: <Widget>[
|
||||||
Positioned(
|
Positioned(
|
||||||
bottom: 12.0,
|
bottom: 12.0,
|
||||||
left: 16.0,
|
left: 16.0,
|
||||||
child: Row(
|
child: Row(
|
||||||
children: [
|
children: [
|
||||||
SizedBox(
|
SizedBox(
|
||||||
height: 40,
|
height: 40,
|
||||||
width: 40,
|
width: 40,
|
||||||
child: Container(
|
child: Container(
|
||||||
decoration: const BoxDecoration(
|
decoration: const BoxDecoration(
|
||||||
image: DecorationImage(
|
image: DecorationImage(
|
||||||
fit: BoxFit.cover,
|
fit: BoxFit.cover,
|
||||||
image: AssetImage(
|
image: AssetImage(
|
||||||
'assets/images/drawer/user.png')))),
|
'assets/images/drawer/user.png',
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
horizontalSpaceSmall,
|
),
|
||||||
StoreConnector<AppState, UserState>(
|
horizontalSpaceSmall,
|
||||||
converter: (store) => store.state.userState!,
|
StoreConnector<AppState, UserState>(
|
||||||
builder: (context, snapshot) {
|
converter: (store) => store.state.userState!,
|
||||||
return Column(
|
builder: (context, snapshot) {
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
return Column(
|
||||||
children: [
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
Text(snapshot.auth?.username ?? '',
|
children: [
|
||||||
style: TextStyle(fontSize: 16.0)),
|
Text(
|
||||||
Text('Продавец', style: TextStyle(fontSize: 12)),
|
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(
|
child: Material(
|
||||||
color: Colors.transparent,
|
color: Colors.transparent,
|
||||||
child: InkWell(
|
child: InkWell(
|
||||||
onTap: onTap,
|
onTap: disable ? () {} : onTap,
|
||||||
child: Padding(
|
child: Padding(
|
||||||
padding:
|
padding:
|
||||||
const EdgeInsets.symmetric(vertical: 15.0, horizontal: 20.0),
|
const EdgeInsets.symmetric(vertical: 15.0, horizontal: 20.0),
|
||||||
|
|
@ -180,12 +229,13 @@ class AppDrawer extends StatelessWidget {
|
||||||
child: Text(
|
child: Text(
|
||||||
text,
|
text,
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
fontSize: 14.0,
|
fontSize: 14.0,
|
||||||
color: disable
|
color: disable
|
||||||
? disableColor
|
? disableColor
|
||||||
: isDanger
|
: isDanger
|
||||||
? dangerColor
|
? dangerColor
|
||||||
: textColor),
|
: textColor,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
],
|
],
|
||||||
|
|
@ -198,10 +248,11 @@ class AppDrawer extends StatelessWidget {
|
||||||
|
|
||||||
Widget _createDrawerSectionTitle({required String text}) {
|
Widget _createDrawerSectionTitle({required String text}) {
|
||||||
return Padding(
|
return Padding(
|
||||||
padding: const EdgeInsets.all(20.0),
|
padding: const EdgeInsets.symmetric(horizontal: 20.0, vertical: 10.0),
|
||||||
child: Text(
|
child: Text(
|
||||||
text,
|
text,
|
||||||
style: const TextStyle(fontSize: 10.0, color: placeholderColor),
|
style: const TextStyle(fontSize: 10.0, color: placeholderColor),
|
||||||
));
|
),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,4 @@
|
||||||
import 'package:flutter/material.dart';
|
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/shared_styles.dart';
|
||||||
import 'package:satu/shared/ui_helpers.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';
|
import 'note_text.dart';
|
||||||
|
|
||||||
class InputField extends StatefulWidget {
|
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(
|
InputField(
|
||||||
{required this.controller,
|
{required this.controller,
|
||||||
|
|
@ -48,6 +29,25 @@ class InputField extends StatefulWidget {
|
||||||
this.multiline = false,
|
this.multiline = false,
|
||||||
this.smallVersion = false,
|
this.smallVersion = false,
|
||||||
this.labelText});
|
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
|
@override
|
||||||
_InputFieldState createState() => _InputFieldState();
|
_InputFieldState createState() => _InputFieldState();
|
||||||
|
|
@ -105,7 +105,7 @@ class _InputFieldState extends State<InputField> {
|
||||||
});
|
});
|
||||||
FocusScope.of(context)
|
FocusScope.of(context)
|
||||||
.requestFocus(FocusNode()); //remove focus
|
.requestFocus(FocusNode()); //remove focus
|
||||||
WidgetsBinding.instance!.addPostFrameCallback(
|
WidgetsBinding.instance.addPostFrameCallback(
|
||||||
(_) => widget.controller.clear()); // clear content
|
(_) => widget.controller.clear()); // clear content
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,27 @@ import 'package:satu/shared/ui_helpers.dart';
|
||||||
import 'note_text.dart';
|
import 'note_text.dart';
|
||||||
|
|
||||||
class InputFieldRounded extends StatefulWidget {
|
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 TextEditingController controller;
|
||||||
final TextInputType textInputType;
|
final TextInputType textInputType;
|
||||||
final bool password;
|
final bool password;
|
||||||
|
|
@ -28,27 +49,6 @@ class InputFieldRounded extends StatefulWidget {
|
||||||
final String? labelText;
|
final String? labelText;
|
||||||
final String? suffixText;
|
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
|
@override
|
||||||
_InputFieldRoundedState createState() => _InputFieldRoundedState();
|
_InputFieldRoundedState createState() => _InputFieldRoundedState();
|
||||||
}
|
}
|
||||||
|
|
@ -90,10 +90,12 @@ class _InputFieldRoundedState extends State<InputFieldRounded> {
|
||||||
minHeight: widget.smallVersion ? 40.h : fieldHeight),
|
minHeight: widget.smallVersion ? 40.h : fieldHeight),
|
||||||
alignment: Alignment.centerLeft,
|
alignment: Alignment.centerLeft,
|
||||||
padding: fieldPadding,
|
padding: fieldPadding,
|
||||||
decoration:
|
decoration: widget.isReadOnly
|
||||||
widget.isReadOnly ? disabledFieldDecoration : BoxDecoration( color: whiteColor , borderRadius: BorderRadius.circular(6.0), boxShadow: [
|
? disabledFieldDecoration
|
||||||
inputShadowBox
|
: BoxDecoration(
|
||||||
]),
|
color: whiteColor,
|
||||||
|
borderRadius: BorderRadius.circular(6.0),
|
||||||
|
boxShadow: [inputShadowBox]),
|
||||||
child: Row(
|
child: Row(
|
||||||
children: <Widget>[
|
children: <Widget>[
|
||||||
GestureDetector(
|
GestureDetector(
|
||||||
|
|
@ -106,7 +108,7 @@ class _InputFieldRoundedState extends State<InputFieldRounded> {
|
||||||
});
|
});
|
||||||
FocusScope.of(context)
|
FocusScope.of(context)
|
||||||
.requestFocus(new FocusNode()); //remove focus
|
.requestFocus(new FocusNode()); //remove focus
|
||||||
WidgetsBinding.instance!.addPostFrameCallback(
|
WidgetsBinding.instance.addPostFrameCallback(
|
||||||
(_) => widget.controller.clear()); // clear content
|
(_) => widget.controller.clear()); // clear content
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
@ -123,9 +125,7 @@ class _InputFieldRoundedState extends State<InputFieldRounded> {
|
||||||
child: TextFormField(
|
child: TextFormField(
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
color: textColor,
|
color: textColor,
|
||||||
fontSize: widget.smallVersion
|
fontSize: widget.smallVersion ? 12 : 14),
|
||||||
? 12
|
|
||||||
: 14),
|
|
||||||
controller: widget.controller,
|
controller: widget.controller,
|
||||||
keyboardType: widget.textInputType,
|
keyboardType: widget.textInputType,
|
||||||
focusNode: widget.fieldFocusNode,
|
focusNode: widget.fieldFocusNode,
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,3 @@
|
||||||
import 'package:flutter/cupertino.dart';
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:satu/shared/app_colors.dart';
|
import 'package:satu/shared/app_colors.dart';
|
||||||
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,5 @@
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:satu/shared/app_colors.dart';
|
import 'package:satu/shared/app_colors.dart';
|
||||||
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
|
||||||
|
|
||||||
class NoteText extends StatelessWidget {
|
class NoteText extends StatelessWidget {
|
||||||
const NoteText(this.text, {this.textAlign, this.color, this.fontSize});
|
const NoteText(this.text, {this.textAlign, this.color, this.fontSize});
|
||||||
|
|
|
||||||
|
|
@ -40,9 +40,7 @@ class _BarcodePermissionWidget extends StatefulWidget {
|
||||||
class _BarcodePermissionWidgetState extends State<_BarcodePermissionWidget> {
|
class _BarcodePermissionWidgetState extends State<_BarcodePermissionWidget> {
|
||||||
bool _isGranted = false;
|
bool _isGranted = false;
|
||||||
|
|
||||||
bool _useCameraScan = true;
|
|
||||||
|
|
||||||
String _inputValue = "";
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,6 @@
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
|
||||||
import 'package:satu/shared/app_colors.dart';
|
import 'package:satu/shared/app_colors.dart';
|
||||||
import 'package:satu/shared/ui_helpers.dart';
|
import 'package:satu/shared/ui_helpers.dart';
|
||||||
import 'package:satu/views/work/tabs/component/product_list_item.dart';
|
|
||||||
|
|
||||||
class ProductTitleWidget extends StatelessWidget {
|
class ProductTitleWidget extends StatelessWidget {
|
||||||
const ProductTitleWidget(
|
const ProductTitleWidget(
|
||||||
|
|
|
||||||
51
pubspec.lock
51
pubspec.lock
|
|
@ -175,7 +175,7 @@ packages:
|
||||||
name: collection
|
name: collection
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.15.0"
|
version: "1.16.0"
|
||||||
convert:
|
convert:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
|
@ -252,7 +252,7 @@ packages:
|
||||||
name: fake_async
|
name: fake_async
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.2.0"
|
version: "1.3.0"
|
||||||
ffi:
|
ffi:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
|
@ -286,13 +286,20 @@ packages:
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.1.7"
|
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:
|
flutter_redux:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
name: flutter_redux
|
name: flutter_redux
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.8.2"
|
version: "0.10.0"
|
||||||
flutter_screenutil:
|
flutter_screenutil:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
|
|
@ -358,7 +365,7 @@ packages:
|
||||||
name: grouped_list
|
name: grouped_list
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "4.2.0"
|
version: "5.1.2"
|
||||||
hex:
|
hex:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
|
@ -408,6 +415,13 @@ packages:
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.4.2"
|
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:
|
intl:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
|
|
@ -428,7 +442,7 @@ packages:
|
||||||
name: js
|
name: js
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.6.3"
|
version: "0.6.4"
|
||||||
json_annotation:
|
json_annotation:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
|
@ -443,13 +457,13 @@ packages:
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "6.2.0"
|
version: "6.2.0"
|
||||||
lint:
|
lints:
|
||||||
dependency: "direct dev"
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: lint
|
name: lints
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.8.2"
|
version: "2.0.0"
|
||||||
location_permissions:
|
location_permissions:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
|
|
@ -491,7 +505,7 @@ packages:
|
||||||
name: material_color_utilities
|
name: material_color_utilities
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.1.3"
|
version: "0.1.4"
|
||||||
material_design_icons_flutter:
|
material_design_icons_flutter:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
|
|
@ -540,7 +554,7 @@ packages:
|
||||||
name: path
|
name: path
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.8.0"
|
version: "1.8.1"
|
||||||
path_drawing:
|
path_drawing:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
|
@ -805,6 +819,13 @@ packages:
|
||||||
description: flutter
|
description: flutter
|
||||||
source: sdk
|
source: sdk
|
||||||
version: "0.0.99"
|
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:
|
source_gen:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
|
@ -825,7 +846,7 @@ packages:
|
||||||
name: source_span
|
name: source_span
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.8.1"
|
version: "1.8.2"
|
||||||
sqflite:
|
sqflite:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
|
|
@ -888,7 +909,7 @@ packages:
|
||||||
name: test_api
|
name: test_api
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.4.8"
|
version: "0.4.9"
|
||||||
timing:
|
timing:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
|
@ -986,7 +1007,7 @@ packages:
|
||||||
name: vector_math
|
name: vector_math
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.1.1"
|
version: "2.1.2"
|
||||||
watcher:
|
watcher:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
|
@ -1030,5 +1051,5 @@ packages:
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "3.1.1"
|
version: "3.1.1"
|
||||||
sdks:
|
sdks:
|
||||||
dart: ">=2.16.0 <3.0.0"
|
dart: ">=2.17.3 <3.0.0"
|
||||||
flutter: ">=2.10.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
|
# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
|
||||||
version: 1.0.0+1
|
version: 1.0.0+1
|
||||||
|
|
||||||
|
|
||||||
environment:
|
environment:
|
||||||
sdk: ">=2.14.0 <3.0.0"
|
sdk: ">=2.17.3 <3.0.0"
|
||||||
|
|
||||||
dependencies:
|
dependencies:
|
||||||
flutter:
|
flutter:
|
||||||
sdk: flutter
|
sdk: flutter
|
||||||
cupertino_icons: ^1.0.5
|
cupertino_icons: ^1.0.5
|
||||||
redux: ^5.0.0
|
redux: ^5.0.0
|
||||||
flutter_redux: ^0.8.2
|
flutter_redux: ^0.10.0
|
||||||
redux_thunk: ^0.4.0
|
redux_thunk: ^0.4.0
|
||||||
redux_persist: ^0.9.0
|
redux_persist: ^0.9.0
|
||||||
redux_persist_flutter: ^0.9.0
|
redux_persist_flutter: ^0.9.0
|
||||||
|
|
@ -53,7 +54,8 @@ dependencies:
|
||||||
ai_barcode: ^3.2.0
|
ai_barcode: ^3.2.0
|
||||||
permission_handler: ^8.3.0
|
permission_handler: ^8.3.0
|
||||||
flutter_svg: ^0.23.0+1
|
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
|
flutter_bluetooth_basic: ^0.1.7
|
||||||
location_permissions: ^4.0.1
|
location_permissions: ^4.0.1
|
||||||
esc_pos_utils: ^1.1.0
|
esc_pos_utils: ^1.1.0
|
||||||
|
|
@ -62,9 +64,14 @@ dev_dependencies:
|
||||||
build_runner: ^2.1.5
|
build_runner: ^2.1.5
|
||||||
flutter_test:
|
flutter_test:
|
||||||
sdk: flutter
|
sdk: flutter
|
||||||
lint: ^1.7.2
|
|
||||||
json_serializable: ^6.0.1
|
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
|
# For information on the generic Dart part of this file, see the
|
||||||
# following page: https://dart.dev/tools/pub/pubspec
|
# following page: https://dart.dev/tools/pub/pubspec
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue