dictionaries

null-safety-migration
suvaysov 2022-06-28 16:13:59 +06:00
parent 44a6de4f58
commit 34b669eea0
86 changed files with 1466 additions and 949 deletions

View File

@ -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

View File

@ -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',
);
} }

View File

@ -1,4 +1,3 @@
import 'package:flutter/foundation.dart';
class DialogRequest { class DialogRequest {
DialogRequest( DialogRequest(

View File

@ -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;

View File

@ -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);
}
}

View File

@ -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,
};

View File

@ -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;
} }

View File

@ -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);
}
}

View File

@ -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,
};

View File

@ -1,4 +1,3 @@
import 'package:satu/core/utils/utils_parse.dart';
class TransactionDao { class TransactionDao {
TransactionDao(); TransactionDao();

View File

@ -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);
} }

View File

@ -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>{

View File

@ -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;
}
}

View File

@ -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,
};
}
} }

View File

@ -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});

View File

@ -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;
} }

View File

@ -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) {

View File

@ -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';

View File

@ -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>();

View File

@ -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) {

View File

@ -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;

View File

@ -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;

View File

@ -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) {

View File

@ -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,

View File

@ -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);
} }
} }

View File

@ -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,
);
}
} }

View File

@ -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,

View File

@ -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,

View File

@ -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,30 +124,49 @@ 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);
@ -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);

View File

@ -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) {

View File

@ -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();

View File

@ -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,

View File

@ -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;
} }
} }

View File

@ -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) {

View File

@ -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) {

View File

@ -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';

View File

@ -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(

View File

@ -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;
});
} }
} }

View File

@ -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;
});
} }
} }

View File

@ -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,11 +79,18 @@ 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, separatorBuilder: (BuildContext context, int index) {
itemBuilder: (BuildContext context, int index) { return const Divider(
final CategoryRowDao category = items[index]; height: 1.0,
color: disableColor,
);
},
pagingController: _pagingController,
builderDelegate: PagedChildBuilderDelegate<CategoryResponse>(
itemBuilder: (BuildContext context, CategoryResponse category,
int index) {
return DictionaryTile( return DictionaryTile(
key: Key('category_${category.id}'), key: Key('category_${category.id}'),
onPress: () => _navigatorService.push(categoryEditRoute, onPress: () => _navigatorService.push(categoryEditRoute,
@ -87,26 +100,22 @@ class _CategoryDictionaryViewState extends State<CategoryDictionaryView> {
children: [ children: [
Text( Text(
category.name, category.name,
style: const TextStyle(fontSize: 12, color: textColor), style:
const TextStyle(fontSize: 12, color: textColor),
), ),
Text( Text(
category.parentName.isEmpty category.parentId ==null
? 'Корневая категория' ? 'Корневая категория'
: 'Родитель: ${category.parentName}', : 'Родитель: ${category.parentId}',
style: const TextStyle( style: const TextStyle(
fontSize: 10, color: placeholderColor)), fontSize: 10, color: placeholderColor)),
], ],
), ),
); );
}, },
separatorBuilder: (BuildContext context, int index) {
return const Divider(
height: 1.0,
color: disableColor,
);
},
), ),
), ),
)
], ],
), ),
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;
});
} }
} }

View File

@ -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,
),
),
],
),
),
);
}
}

View File

@ -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);
}
}
}

View File

@ -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);
} }
} }
} }

View File

@ -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,11 +100,18 @@ 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,
color: disableColor,
);
},
pagingController: _pagingController,
builderDelegate: PagedChildBuilderDelegate<GoodResponse>(
itemBuilder:
(BuildContext context, GoodResponse good, int index) {
return DictionaryTile( return DictionaryTile(
onPress: () { onPress: () {
locator<NavigatorService>() locator<NavigatorService>()
@ -111,19 +124,15 @@ class _GoodsDictionaryViewState extends State<GoodsDictionaryView> {
), ),
); );
}, },
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: () =>
locator<NavigatorService>()
.push(goodsEditRoute, arguments: GoodRowDao('', '')), .push(goodsEditRoute, arguments: GoodRowDao('', '')),
child: const Icon( child: const Icon(
Icons.add_rounded, Icons.add_rounded,
@ -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;
});
} }
} }

View File

@ -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,8 +48,7 @@ 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(
@ -81,8 +76,8 @@ class _LoginViewState extends State<LoginView> {
), ),
verticalSpaceMedium, verticalSpaceMedium,
Padding( Padding(
padding: padding: EdgeInsets.only(
EdgeInsets.only(left: 45.sp, right: 45.sp, top: 30.sp), left: 45.sp, right: 45.sp, top: 30.sp),
child: BusyButton( child: BusyButton(
title: 'ВОЙТИ', title: 'ВОЙТИ',
busy: vm.isLoading!, busy: vm.isLoading!,
@ -101,7 +96,6 @@ class _LoginViewState extends State<LoginView> {
), ),
); );
}, },
)); ));
}); });
} }
@ -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});
} }

View File

@ -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;
} }

View File

@ -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';

View File

@ -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';

View File

@ -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';

View File

@ -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() {

View File

@ -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';

View File

@ -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) {

View File

@ -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(

View File

@ -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'))
], ],
), ),
], ],

View File

@ -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(

View File

@ -2,20 +2,21 @@ 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( Container(
width: 16, width: 16,
height: 50, height: 50,
@ -24,12 +25,10 @@ class TransactionItem extends StatelessWidget {
// Icons.memory // Icons.memory
// ), // ),
), ),
Expanded( Expanded(
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
Text( Text(
fullName, fullName,
style: TextStyle( style: TextStyle(
@ -38,7 +37,6 @@ class TransactionItem extends StatelessWidget {
fontWeight: FontWeight.bold, fontWeight: FontWeight.bold,
), ),
), ),
Text( Text(
status, status,
style: TextStyle( style: TextStyle(
@ -47,22 +45,18 @@ class TransactionItem extends StatelessWidget {
fontWeight: FontWeight.w500, fontWeight: FontWeight.w500,
), ),
), ),
], ],
), ),
), ),
Text( Text(
(received ? "+" : "-") + r" $ " + amount + " KZT", (received ? '+' : '-') + r' $ ' + amount + ' KZT',
style: TextStyle( style: TextStyle(
color: received ? Colors.green : Colors.red, color: received ? Colors.green : Colors.red,
fontSize: 16, fontSize: 16,
fontWeight: FontWeight.bold, fontWeight: FontWeight.bold,
), ),
), ),
]),
]
),
); );
} }
} }

View File

@ -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

View File

@ -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,

View File

@ -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';

View File

@ -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); navigateCategory(0);
_searchTextController.clear(); _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;
}); });
} }
} }

View File

@ -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) {

View File

@ -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';

View File

@ -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})

View File

@ -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';

View File

@ -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({

View File

@ -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';

View File

@ -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';

View File

@ -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';

View File

@ -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) {

View File

@ -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})

View File

@ -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 {

View File

@ -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();
} }

View File

@ -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();
} }

View File

@ -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')),
), ),
) )
], ],

View File

@ -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';
@ -33,18 +33,30 @@ class AppDrawer extends StatelessWidget {
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(
icon: Icons.archive,
text: 'Остатки',
onTap: () {
Navigator.of(context).pop();
Redux.store!.dispatch(navigateDrawer(AnalyticsView));
},
disable: true,
),
_createDrawerItem( _createDrawerItem(
svgFile: 'inventarization', svgFile: 'inventarization',
text: 'Инвентаризация', text: 'Инвентаризация',
disable: true), disable: true,
),
_createDrawerSectionTitle(text: 'СПРАВОЧНИКИ'), _createDrawerSectionTitle(text: 'СПРАВОЧНИКИ'),
_createDrawerItem( _createDrawerItem(
svgFile: 'categories', svgFile: 'categories',
@ -52,19 +64,32 @@ class AppDrawer extends StatelessWidget {
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',
@ -72,18 +97,26 @@ class AppDrawer extends StatelessWidget {
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: ''),
], ],
), ),
@ -100,8 +133,11 @@ class AppDrawer extends StatelessWidget {
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,
@ -115,7 +151,11 @@ class AppDrawer extends StatelessWidget {
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, horizontalSpaceSmall,
StoreConnector<AppState, UserState>( StoreConnector<AppState, UserState>(
@ -124,15 +164,24 @@ class AppDrawer extends StatelessWidget {
return Column( return Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
Text(snapshot.auth?.username ?? '', Text(
style: TextStyle(fontSize: 16.0)), snapshot.auth?.username ?? '',
Text('Продавец', style: TextStyle(fontSize: 12)), 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),
@ -185,7 +234,8 @@ class AppDrawer extends StatelessWidget {
? 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),
)); ),
);
} }
} }

View File

@ -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';

View File

@ -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
],
);
}
}

View File

@ -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
} }
}, },

View File

@ -8,26 +8,6 @@ import 'package:satu/shared/ui_helpers.dart';
import 'note_text.dart'; import 'note_text.dart';
class InputFieldRounded extends StatefulWidget { class InputFieldRounded 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;
InputFieldRounded( InputFieldRounded(
{required this.controller, {required this.controller,
required this.placeholder, required this.placeholder,
@ -49,6 +29,26 @@ class InputFieldRounded extends StatefulWidget {
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
_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,

View File

@ -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';

View File

@ -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});

View File

@ -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() {

View File

@ -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(

View File

@ -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"

View File

@ -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