Calculator

4.4
Serik.Uvaissov 2020-06-22 20:10:48 +06:00
parent d916f638fb
commit 2e2033fec1
66 changed files with 2206 additions and 521 deletions

View File

@ -1,49 +0,0 @@
import 'package:flutter/foundation.dart';
import 'package:logger/logger.dart';
import '../logger.dart';
class BaseViewModel extends ChangeNotifier {
String _title;
bool _busy;
Logger log;
bool _isDisposed = false;
BaseViewModel({
bool busy = false,
String title,
}) : _busy = busy,
_title = title {
log = getLogger(title ?? this.runtimeType.toString());
}
bool get busy => this._busy;
bool get isDisposed => this._isDisposed;
String get title => _title ?? this.runtimeType.toString();
set busy(bool busy) {
log.i(
'busy: '
'$title is entering '
'${busy ? 'busy' : 'free'} state',
);
this._busy = busy;
notifyListeners();
}
@override
void notifyListeners() {
if (!isDisposed) {
super.notifyListeners();
} else {
log.w('notifyListeners: Notify listeners called after '
'${title ?? this.runtimeType.toString()} has been disposed');
}
}
@override
void dispose() {
log.i('dispose');
_isDisposed = true;
super.dispose();
}
}

View File

@ -4,16 +4,19 @@ const String Category_tableName = 'goods_category';
const String Category_columnId = 'id'; const String Category_columnId = 'id';
const String Category_columnParentIn = 'parent_id'; const String Category_columnParentIn = 'parent_id';
const String Category_columnName = 'name'; const String Category_columnName = 'name';
const String Category_columnAppCompanyId = 'app_company_id';
class Category { class Category {
int id; int id;
int parentIn; int parentIn;
String name; String name;
int appCompanyId;
Map<String, dynamic> toMap() { Map<String, dynamic> toMap() {
var map = <String, dynamic>{ var map = <String, dynamic>{
Category_columnParentIn: parentIn, Category_columnParentIn: parentIn,
Category_columnName: name, Category_columnName: name,
Category_columnAppCompanyId: appCompanyId
}; };
if (id != null) { if (id != null) {
map[Category_columnId] = id; map[Category_columnId] = id;
@ -27,12 +30,14 @@ class Category {
id = map[Category_columnId]; id = map[Category_columnId];
parentIn = map[Category_columnParentIn]; parentIn = map[Category_columnParentIn];
name = map[Category_columnName]; name = map[Category_columnName];
appCompanyId = map[Category_columnAppCompanyId];
} }
Category.fromJson(Map<String, dynamic> map) { Category.fromJson(Map<String, dynamic> map) {
id = map[Category_columnId]; id = map[Category_columnId];
parentIn = map[Category_columnParentIn]; parentIn = map[Category_columnParentIn];
name = map[Category_columnName]; name = map[Category_columnName];
appCompanyId = map[Category_columnAppCompanyId];
} }
} }

View File

@ -7,6 +7,12 @@ const String Goog_columnName = 'name';
const String Goog_columnPrice = 'price'; const String Goog_columnPrice = 'price';
const String Goog_columnCategoryId = 'category_id'; const String Goog_columnCategoryId = 'category_id';
const String Goog_columnEan = 'ean'; const String Goog_columnEan = 'ean';
const String Goog_columnAppCompanyId = 'app_company_id';
const String Goog_columnDescription = 'description';
const String Goog_columnShowPrice = 'show_price';
const String Goog_columnOkei = 'okei';
const String Goog_columnDiscount = 'discount';
class Good { class Good {
int id; int id;
@ -15,6 +21,11 @@ class Good {
double price; double price;
int categoryId; int categoryId;
String ean; String ean;
int appCompanyId;
String description;
double showPrice;
int okei;
double discount;
Map<String, dynamic> toMap() { Map<String, dynamic> toMap() {
var map = <String, dynamic>{ var map = <String, dynamic>{
@ -23,6 +34,11 @@ class Good {
Goog_columnPrice: price, Goog_columnPrice: price,
Goog_columnCategoryId: categoryId, Goog_columnCategoryId: categoryId,
Goog_columnEan: ean, Goog_columnEan: ean,
Goog_columnAppCompanyId: appCompanyId,
Goog_columnDescription: description,
Goog_columnShowPrice: showPrice,
Goog_columnOkei: okei,
Goog_columnDiscount: discount
}; };
if (id != null) { if (id != null) {
map[Goog_columnId] = id; map[Goog_columnId] = id;
@ -39,6 +55,11 @@ class Good {
price = map[Goog_columnPrice]?.toDouble(); price = map[Goog_columnPrice]?.toDouble();
categoryId = map[Goog_columnCategoryId]; categoryId = map[Goog_columnCategoryId];
ean = map[Goog_columnEan]; ean = map[Goog_columnEan];
appCompanyId= map[Goog_columnAppCompanyId];
description = map[Goog_columnDescription];
showPrice = map[Goog_columnShowPrice]?.toDouble();
okei = map[Goog_columnOkei];
discount = map[Goog_columnDiscount]?.toDouble();
} }
Good.fromJson(Map<String, dynamic> map) { Good.fromJson(Map<String, dynamic> map) {
@ -48,6 +69,11 @@ class Good {
price = double.parse(map[Goog_columnPrice]); price = double.parse(map[Goog_columnPrice]);
categoryId = map[Goog_columnCategoryId]; categoryId = map[Goog_columnCategoryId];
ean = map[Goog_columnEan]; ean = map[Goog_columnEan];
appCompanyId = map[Goog_columnAppCompanyId];
description = map[Goog_columnDescription];
showPrice = map[Goog_columnShowPrice]?.toDouble();
okei = map[Goog_columnOkei];
discount = map[Goog_columnDiscount]?.toDouble();
} }
} }

View File

@ -7,18 +7,36 @@ const String Service_columnName = 'name';
const String Service_columnPrice = 'price'; const String Service_columnPrice = 'price';
const String Service_columnCategoryId = 'category_id'; const String Service_columnCategoryId = 'category_id';
const String Service_columnEan = 'ean'; const String Service_columnEan = 'ean';
const String Service_columnAppCompanyId = 'app_company_id';
const String Service_columnDescription = 'description';
const String Service_columnShowPrice = 'show_price';
const String Service_columnOkei = 'okei';
const String Service_columnDiscount = 'discount';
class Service { class Service {
int id; int id;
int articul; int articul;
String name; String name;
double price; double price;
String ean;
int appCompanyId;
String description;
double showPrice;
String okei;
double discount;
Map<String, dynamic> toMap() { Map<String, dynamic> toMap() {
var map = <String, dynamic>{ var map = <String, dynamic>{
Service_columnArticul: articul, Service_columnArticul: articul,
Service_columnName: name, Service_columnName: name,
Service_columnPrice: price, Service_columnPrice: price,
Service_columnAppCompanyId: appCompanyId,
Service_columnDescription: description,
Service_columnShowPrice: showPrice,
Service_columnOkei: okei,
Service_columnDiscount: discount
}; };
if (id != null) { if (id != null) {
map[Service_columnId] = id; map[Service_columnId] = id;
@ -33,13 +51,24 @@ class Service {
articul = map[Service_columnArticul]; articul = map[Service_columnArticul];
name = map[Service_columnName]; name = map[Service_columnName];
price = map[Service_columnPrice]?.toDouble(); price = map[Service_columnPrice]?.toDouble();
appCompanyId = map[Service_columnAppCompanyId];
description = map[Service_columnDescription];
showPrice = map[Service_columnShowPrice]?.toDouble();
okei = map[Service_columnOkei];
discount = map[Service_columnDiscount]?.toDouble();
} }
Service.fromJson(Map<String, dynamic> map) { Service.fromJson(Map<String, dynamic> map) {
id = map[Service_columnId]; id = map[Service_columnId];
articul = map[Service_columnArticul]; articul = map[Service_columnArticul];
name = map[Service_columnName]; name = map[Service_columnName];
price = map[Service_columnPrice]?.toDouble(); } price = map[Service_columnPrice]?.toDouble();
appCompanyId = map[Service_columnAppCompanyId];
description = map[Service_columnDescription];
showPrice = map[Service_columnShowPrice]?.toDouble();
okei = map[Service_columnOkei];
discount = map[Service_columnDiscount]?.toDouble();
}
} }

View File

@ -38,15 +38,25 @@ import 'package:logger/logger.dart';
// } // }
// } // }
//Logger getLogger(String className) {
// //return Logger(printer: SimpleLogPrinter(className));
// return Logger(
// printer: PrettyPrinter(
// methodCount: 1, // number of method calls to be displayed
// errorMethodCount: 1, // number of method calls if stacktrace is provided
// lineLength: 120, // width of the output
// colors: false, // Colorful log messages
// printEmojis: false, // Print an emoji for each log message
// printTime: false // Should each log print contain a timestamp
// ));
//}
Logger getLogger(String className) { Logger getLogger(String className) {
//return Logger(printer: SimpleLogPrinter(className)); //return Logger(printer: SimpleLogPrinter(className));
return Logger( return Logger(
printer: PrettyPrinter( printer: SimplePrinter(
methodCount: 2, // number of method calls to be displayed
errorMethodCount: 8, // number of method calls if stacktrace is provided
lineLength: 120, // width of the output
colors: true, // Colorful log messages colors: true, // Colorful log messages
printEmojis: true, // Print an emoji for each log message
printTime: false // Should each log print contain a timestamp printTime: false // Should each log print contain a timestamp
)); ));
} }

View File

@ -1,12 +0,0 @@
import 'package:aman_kassa_flutter/core/entity/Goods.dart';
class ProductDao {
final String name;
final num price;
num count;
final Good good;
ProductDao( {this.name, this.price, this.count, this.good});
}

View File

@ -1,3 +1,4 @@
import '../utilsParse.dart';
import 'user.dart'; import 'user.dart';
class AuthResponse { class AuthResponse {
@ -17,11 +18,6 @@ class AuthResponse {
} }
} }
List<String> parseListString(json){
if(json==null) return null;
return new List<String>.from(json);
}
class AuthBody { class AuthBody {
final List<String> email; final List<String> email;
final List<String> password; final List<String> password;

View File

@ -0,0 +1,14 @@
class CalcModel {
String num1;
String num2;
bool closed;
String operation;
CalcModel({this.num1, this.num2, this.operation, this.closed = false});
@override
String toString() {
// TODO: implement toString
return 'num1: $num1 num2:$num2 operation:$operation closed:$closed';
}
}

View File

@ -0,0 +1,22 @@
import 'package:aman_kassa_flutter/core/models/check_item.dart';
class CheckData {
final String type;
num card;
final List<CheckItem> items;
CheckData({this.type, this.card, this.items});
static CheckData fromJson(Map<String, dynamic> json) {
return CheckData(
type: json['type'],
card: json['card'],
items: json['items'],
);
}
Map<String, dynamic> toJson() =>
{
'type': type,
'card': card,
'items': items.map((e) => e.toJson()).toList()
};
}

View File

@ -0,0 +1,23 @@
class CheckItem {
final String name;
final num cnt;
final num price;
final int articul;
CheckItem({this.name, this.cnt, this.price, this.articul});
static CheckItem fromJson(Map<String, dynamic> json) {
return CheckItem(
name: json['name'],
cnt: json['cnt'],
price: json['price'],
articul: json['articul'],
);
}
Map<String, dynamic> toJson() =>
{
'name': name,
'cnt': cnt,
'price': price,
'articul': articul
};
}

View File

@ -14,13 +14,15 @@ class DialogRequest {
} }
class DialogResponse { class DialogResponse {
final String fieldOne; //final String fieldOne;
final String fieldTwo; //final String fieldTwo;
final String responseText;
final bool confirmed; final bool confirmed;
DialogResponse({ DialogResponse({
this.fieldOne, //this.fieldOne,
this.fieldTwo, //this.fieldTwo,
this.responseText,
this.confirmed, this.confirmed,
}); });
} }

View File

@ -0,0 +1,15 @@
import 'package:aman_kassa_flutter/core/entity/Goods.dart';
import 'package:aman_kassa_flutter/core/entity/Service.dart';
class ProductDao {
final String name;
final num price;
num count;
num total;
final Good good;
final Service service;
ProductDao( {this.name, this.price, this.count, this.total, this.good, this.service });
}

View File

@ -0,0 +1,21 @@
class Smena {
final int id;
final DateTime startedAt;
final DateTime endedAt;
final String message;
Smena({this.id, this.startedAt, this.endedAt, this.message});
static Smena fromJson(Map<String, dynamic> data) => Smena(
id: data['id'],
message: data['message'],
startedAt:
data['started_at'] != null
? DateTime.parse(data['started_at'])
: null,
endedAt:
data['ended_at'] != null
? DateTime.parse(data['ended_at'])
: null,
);
}

View File

@ -1,3 +1,5 @@
const String LoginViewRoute = "LoginView"; const String LoginViewRoute = "LoginView";
const String HomeViewRoute = "HomeView"; const String HomeViewRoute = "HomeView";
const String ImageShowRoute = "ImageShowRoute";
const String PaymentViewRoute = "PaymentView";
// Generate the views here // Generate the views here

View File

@ -1,3 +1,6 @@
import 'package:aman_kassa_flutter/views/check/image_show_container.dart';
import 'package:aman_kassa_flutter/views/payment/payment_view.dart';
import './route_names.dart'; import './route_names.dart';
import 'package:aman_kassa_flutter/views/home/home_view.dart'; import 'package:aman_kassa_flutter/views/home/home_view.dart';
import 'package:aman_kassa_flutter/views/login/login_view.dart'; import 'package:aman_kassa_flutter/views/login/login_view.dart';
@ -15,11 +18,15 @@ Route<dynamic> generateRoute(RouteSettings settings) {
routeName: settings.name, routeName: settings.name,
viewToShow: HomeView(), viewToShow: HomeView(),
); );
// case AddAndEditViewRoute: case PaymentViewRoute:
// var documentToEdit = settings.arguments as Document; PaymentModel model = settings.arguments as PaymentModel;
// return SlideRightRoute(widget:AddAndEditView( return _getPageRoute(
// edittingDocument: documentToEdit, routeName: settings.name,
// )); viewToShow: PaymentView(model: model),
);
case ImageShowRoute:
ImageShowModel data = settings.arguments as ImageShowModel;
return SlideRightRoute(widget:ImageShowContainer(data));
default: default:
return MaterialPageRoute( return MaterialPageRoute(
builder: (_) => Scaffold( builder: (_) => Scaffold(

View File

@ -3,9 +3,10 @@ import 'dart:io';
import 'package:aman_kassa_flutter/core/base/base_service.dart'; import 'package:aman_kassa_flutter/core/base/base_service.dart';
import 'package:aman_kassa_flutter/core/entity/Goods.dart'; import 'package:aman_kassa_flutter/core/entity/Goods.dart';
import 'package:aman_kassa_flutter/core/models/Message.dart'; import 'package:aman_kassa_flutter/core/models/message.dart';
import 'package:aman_kassa_flutter/core/models/Response.dart'; import 'package:aman_kassa_flutter/core/models/response.dart';
import '../models/authResponse.dart'; import 'package:aman_kassa_flutter/core/models/smena.dart';
import '../models/auth_response.dart';
import 'package:http/http.dart' as http; import 'package:http/http.dart' as http;
@ -15,32 +16,92 @@ class ApiService extends BaseService {
var client = new http.Client(); var client = new http.Client();
Future<AuthBody> authenticate(String email, String password) async { Future<AuthBody> authenticate(String email, String password, { bool statusCheck = true}) async {
Map<String, String> requestBody = <String, String>{ Map<String, String> requestBody = <String, String>{
'email': email, 'email': email,
'password': password 'password': password
}; };
var response = await requestFormData('/authenticate', requestBody); String response = await requestFormData('/authenticate', requestBody, statusCheck: statusCheck );
final respStr = await response.stream.bytesToString();
AuthResponse aman = AuthResponse.fromJson(json.decode(respStr)); AuthResponse aman = AuthResponse.fromJson(json.decode(response));
return aman.body; return aman.body;
} }
Future<Response<Message>> isActive(String token) async { Future<Response<Message>> isActive(String token) async {
Map<String, String> requestBody = <String, String>{'api_token': token}; Map<String, String> requestBody = <String, String>{'api_token': token};
var response = await requestFormData('/test_auth', requestBody); var response = await requestFormData('/test_auth', requestBody);
final respStr = await response.stream.bytesToString(); return Response.fromJson(json.decode(response), Message.fromJson);
return Response.fromJson(json.decode(respStr), Message.fromJson);
} }
Future<Response<Message>> logout(String token) async { Future<Response<Message>> logout(String token) async {
Map<String, String> requestBody = <String, String>{'api_token': token}; Map<String, String> requestBody = <String, String>{'api_token': token};
var response = await requestFormData('/logout', requestBody); var response = await requestFormData('/logout', requestBody);
final respStr = await response.stream.bytesToString(); return Response.fromJson(json.decode(response), Message.fromJson);
return Response.fromJson(json.decode(respStr), Message.fromJson);
} }
Future<http.StreamedResponse> requestFormData(String point, Map<String, String> requestBody) async { Future<Response<dynamic>> money(String token) async {
Map<String, String> requestBody = <String, String>{'api_token': token};
var response = await requestFormData('/money', requestBody);
return Response.fromJsonDynamic(json.decode(response));
}
Future<Response<dynamic>> deposit(String token, String sum) async {
Map<String, String> requestBody = <String, String>{'api_token': token, 'summ': sum};
var response = await requestFormData('/deposit', requestBody);
return Response.fromJsonDynamic(json.decode(response));
}
Future<Response<dynamic>> withdrawal(String token, String sum) async {
Map<String, String> requestBody = <String, String>{'api_token': token, 'summ': sum};
var response = await requestFormData('/withdrawal', requestBody);
return Response.fromJsonDynamic(json.decode(response));
}
Future<Response<Smena>> smena(String token) async {
Map<String, String> requestBody = <String, String>{'api_token': token};
var response = await requestFormData('/smena', requestBody);
return Response.fromJson(json.decode(response), Smena.fromJson);
}
Future<Response<Smena>> closeSmena(String token) async {
Map<String, String> requestBody = <String, String>{'api_token': token};
var response = await requestFormData('/close_smena', requestBody);
return Response.fromJson(json.decode(response), Smena.fromJson);
}
Future<Response<Smena>> openSmena(String token) async {
Map<String, String> requestBody = <String, String>{'api_token': token};
var response = await requestFormData('/open_smena', requestBody);
return Response.fromJson(json.decode(response), Smena.fromJson);
}
Future<Response<dynamic>> xReport(String token) async {
Map<String, String> requestBody = <String, String>{'api_token': token};
var response = await requestFormData('/report_x', requestBody);
return Response.fromJsonDynamic(json.decode(response));
}
Future<Response<dynamic>> sell(String token, String checkData) async {
Map<String, String> requestBody = <String, String>{'api_token': token, 'data': checkData};
var response = await requestFormData('/sell', requestBody);
print(response);
return Response.fromJsonDynamic(json.decode(response));
}
Future<Response<dynamic>> sellReturn(String token, String checkData) async {
Map<String, String> requestBody = <String, String>{'api_token': token, 'data': checkData};
var response = await requestFormData('/sell_return', requestBody);
print(response);
return Response.fromJsonDynamic(json.decode(response));
}
Future<String> requestFormData(String point, Map<String, String> requestBody, { bool statusCheck = true } ) async {
Map<String, String> headers = <String, String>{ Map<String, String> headers = <String, String>{
HttpHeaders.contentTypeHeader: "multipart/form-data", HttpHeaders.contentTypeHeader: "multipart/form-data",
HttpHeaders.cacheControlHeader: "no-cache" HttpHeaders.cacheControlHeader: "no-cache"
@ -48,32 +109,38 @@ class ApiService extends BaseService {
var uri = Uri.parse('$endpoint$point'); var uri = Uri.parse('$endpoint$point');
var request = http.MultipartRequest('POST', uri) var request = http.MultipartRequest('POST', uri)
..headers.addAll( ..headers.addAll(headers)
headers) //if u have headers, basic auth, token bearer... Else remove line
..fields.addAll(requestBody); ..fields.addAll(requestBody);
return await request.send();
var response = await request.send();
String body = await response.stream.bytesToString();
if(statusCheck) { //Проверка на авторизованный запрос, необязательный параметр
Response check = Response.fromJsonDynamic(json.decode(body));
if (!check.operation && check.status == 401) {
print('object');
}
}
return body;
} }
Future<Response<dynamic>> getGoodsFromServer(String token) async { Future<Response<dynamic>> getGoodsFromServer(String token) async {
Map<String, String> requestBody = <String, String>{'api_token': token}; Map<String, String> requestBody = <String, String>{'api_token': token};
var response = await requestFormData('/goods', requestBody); var response = await requestFormData('/goods', requestBody);
final respStr = await response.stream.bytesToString(); print(response);
print(respStr); return Response.fromJsonDynamic(json.decode(response));
return Response.fromJsonDynamic(json.decode(respStr));
} }
Future<Response<dynamic>> getCategoryFromServer(String token) async { Future<Response<dynamic>> getCategoryFromServer(String token) async {
Map<String, String> requestBody = <String, String>{'api_token': token}; Map<String, String> requestBody = <String, String>{'api_token': token};
var response = await requestFormData('/goods_category', requestBody); var response = await requestFormData('/goods_category', requestBody);
final respStr = await response.stream.bytesToString(); print(response);
print(respStr); return Response.fromJsonDynamic(json.decode(response));
return Response.fromJsonDynamic(json.decode(respStr));
} }
Future<Response<dynamic>> getServiceFromServer(String token) async { Future<Response<dynamic>> getServiceFromServer(String token) async {
Map<String, String> requestBody = <String, String>{'api_token': token}; Map<String, String> requestBody = <String, String>{'api_token': token};
var response = await requestFormData('/services', requestBody); var response = await requestFormData('/services', requestBody);
final respStr = await response.stream.bytesToString(); print(response);
print(respStr); return Response.fromJsonDynamic(json.decode(response));
return Response.fromJsonDynamic(json.decode(respStr));
} }
} }

View File

@ -5,8 +5,14 @@ import 'package:aman_kassa_flutter/core/entity/Category.dart';
import 'package:aman_kassa_flutter/core/entity/Goods.dart'; import 'package:aman_kassa_flutter/core/entity/Goods.dart';
import 'package:aman_kassa_flutter/core/entity/Service.dart'; import 'package:aman_kassa_flutter/core/entity/Service.dart';
import 'package:aman_kassa_flutter/core/locator.dart'; import 'package:aman_kassa_flutter/core/locator.dart';
import 'package:aman_kassa_flutter/core/models/Response.dart'; import 'package:aman_kassa_flutter/core/models/check_data.dart';
import 'package:aman_kassa_flutter/core/models/check_item.dart';
import 'package:aman_kassa_flutter/core/models/product_dao.dart';
import 'package:aman_kassa_flutter/core/models/response.dart';
import 'package:aman_kassa_flutter/core/models/user.dart';
import 'package:aman_kassa_flutter/core/services/DbService.dart'; import 'package:aman_kassa_flutter/core/services/DbService.dart';
import 'package:aman_kassa_flutter/redux/constants/operation_const.dart';
import 'package:aman_kassa_flutter/redux/store.dart';
import 'ApiService.dart'; import 'ApiService.dart';
@ -15,18 +21,93 @@ class DataService extends BaseService {
final DbService _db = locator<DbService>(); final DbService _db = locator<DbService>();
Future<List<Category>> getCategoriesByParentId({int parentId}) async { Future<List<Category>> getCategoriesByParentId({int parentId}) async {
List<Map<String, dynamic>> list = await _db.queryRowsWithWhere(Category_tableName, '$Category_columnParentIn = ?', [parentId ?? 0 ]); List<Map<String, dynamic>> list = await _db.queryRowsWithWhere(
Category_tableName, '$Category_columnParentIn = ?', [parentId ?? 0]);
return list.map((e) => Category.fromMap(e)).toList(); return list.map((e) => Category.fromMap(e)).toList();
} }
Future<List<Service>> getServices() async {
List<Map<String, dynamic>> list = await _db.queryAllRows(Service_tableName);
return list.map((e) => Service.fromMap(e)).toList();
}
Future<List<Good>> getGoodsByCategoryId({int categoryId}) async { Future<List<Good>> getGoodsByCategoryId({int categoryId}) async {
List<Map<String, dynamic>> list = await _db.queryRowsWithWhere(Goog_tableName, '$Goog_columnCategoryId = ?', [categoryId ?? 0]); List<Map<String, dynamic>> list = await _db.queryRowsWithWhere(
Goog_tableName, '$Goog_columnCategoryId = ?', [categoryId ?? 0]);
return list.map((e) => Good.fromMap(e)).toList(); return list.map((e) => Good.fromMap(e)).toList();
} }
Future<bool> getDataFromServer(String token) async { CheckData _transformProductsToCheckData(
try { {String paymentType,
String tradeType,
List<ProductDao> items}) {
List<CheckItem> itemsList = [];
int iterator = 1;
num summ = 0.0;
items.forEach((el) {
int articul = iterator;
if (el.service != null) {
articul = el.service.articul;
} else if (el.good != null) {
articul = el.good.articul;
}
itemsList.add(CheckItem(
name: el.name ?? 'Позиция №$iterator',
cnt: el.count,
price: el.price,
articul: articul));
summ += el.total;
iterator++;
});
CheckData checkData = CheckData(type: tradeType, items: itemsList);
if ((paymentType ?? 'cash') == 'card') {
checkData.card = summ;
}
print(checkData);
return checkData;
}
Future<Response<dynamic>> sellOrReturn(
{String paymentType,
String tradeType,
String token,
List<ProductDao> items,
String operationType}) async {
try {
CheckData checkData = _transformProductsToCheckData(
paymentType: paymentType, tradeType: tradeType, items: items);
String data = jsonEncode(checkData.toJson());
log.i('token: $token');
log.i('data: $data');
Response<dynamic> response = await (operationType == OperationTypePay
? _api.sell(token, data)
: _api.sellReturn(token, data));
log.i('response status: ${response.status}');
log.i('response operation: ${response.operation}');
if (response.status == 200 && response.operation == true) {
log.i(
'save to db appCompanyId: ${Redux.store.state.userState.user.appCompanyId}, kassaId: ${Redux.store.state.userState.user.kassaId}');
/* save data to db
* data,
* dateTime,
* check,
* appCompanyId,
* kassaId,
* total,
* name,
* type
*/
}
return response;
} catch (e) {
print(e);
}
return null;
}
Future<bool> getDataFromServer(User user) async {
try {
String token = user.token;
Response<dynamic> goods = await _api.getGoodsFromServer(token); Response<dynamic> goods = await _api.getGoodsFromServer(token);
Response<dynamic> categories = await _api.getCategoryFromServer(token); Response<dynamic> categories = await _api.getCategoryFromServer(token);
Response<dynamic> services = await _api.getServiceFromServer(token); Response<dynamic> services = await _api.getServiceFromServer(token);
@ -37,21 +118,21 @@ class DataService extends BaseService {
for (var key in goods.body.keys) { for (var key in goods.body.keys) {
print(goods.body[key]); print(goods.body[key]);
Good row = Good.fromJson(goods.body[key]); Good row = Good.fromJson(goods.body[key]);
_db.insert(Goog_tableName,row.toMap()); await _db.insert(Goog_tableName, row.toMap());
} }
log.i('Inserted ${goods.body.length} to table $Goog_tableName'); log.i('Inserted ${goods.body.length} to table $Goog_tableName');
for (var el in categories.body) { for (var el in categories.body) {
print(el); print(el);
Category row = Category.fromJson(el); Category row = Category.fromJson(el);
_db.insert(Category_tableName,row.toMap()); await _db.insert(Category_tableName, row.toMap());
} }
log.i('Inserted ${categories.body.length} to table $Category_tableName'); log.i('Inserted ${categories.body.length} to table $Category_tableName');
for (var key in services.body.keys) { for (var key in services.body.keys) {
print(services.body[key]); print(services.body[key]);
Service row = Service.fromJson(services.body[key]); Service row = Service.fromJson(services.body[key]);
_db.insert(Service_tableName,row.toMap()); await _db.insert(Service_tableName, row.toMap());
} }
log.i('Inserted ${services.body.length} to table $Service_tableName'); log.i('Inserted ${services.body.length} to table $Service_tableName');

View File

@ -10,7 +10,7 @@ import 'package:path_provider/path_provider.dart';
class DbService extends BaseService { class DbService extends BaseService {
static final _databaseName = "AmanFlutterDb.db"; static final _databaseName = "AmanFlutterDb.db";
static final _databaseVersion = 5; static final _databaseVersion = 15;
// make this a singleton class // make this a singleton class
DbService._privateConstructor(); DbService._privateConstructor();
@ -39,18 +39,17 @@ class DbService extends BaseService {
); );
} }
Future _onUpdate(Database db, int oldVersion, int newVersion) async { Future _onUpdate(Database db, int oldVersion, int newVersion) async {
print('update from $oldVersion to $newVersion'); log.i('update from $oldVersion to $newVersion');
//Goods table //Goods table
await db.execute(''' await db.execute('DROP TABLE IF EXISTS $Goog_tableName;');
DROP TABLE IF EXISTS $Goog_tableName; await db.execute('DROP TABLE IF EXISTS $Category_tableName;');
DROP TABLE IF EXISTS $Category_tableName; await db.execute('DROP TABLE IF EXISTS $Service_tableName;');
DROP TABLE IF EXISTS $Service_tableName; log.i('dropped tables');
''');
_onCreate(db, newVersion); _onCreate(db, newVersion);
} }
Future _onCreate(Database db, int version) async { Future _onCreate(Database db, int version) async {
print('create tables'); log.i('create tables');
//Goods table //Goods table
await db.execute(''' await db.execute('''
CREATE TABLE IF NOT EXISTS $Goog_tableName ( CREATE TABLE IF NOT EXISTS $Goog_tableName (
@ -59,20 +58,35 @@ class DbService extends BaseService {
$Goog_columnName text not null, $Goog_columnName text not null,
$Goog_columnPrice real not null, $Goog_columnPrice real not null,
$Goog_columnCategoryId integer not null, $Goog_columnCategoryId integer not null,
$Goog_columnEan text); $Goog_columnEan text,
$Goog_columnAppCompanyId integer,
$Goog_columnDescription text,
$Goog_columnShowPrice real,
$Goog_columnOkei integer,
$Goog_columnDiscount real
);
'''); ''');
await db.execute(''' await db.execute('''
CREATE TABLE IF NOT EXISTS $Category_tableName ( CREATE TABLE IF NOT EXISTS $Category_tableName (
$Category_columnId integer primary key unique, $Category_columnId integer primary key unique,
$Category_columnName text not null, $Category_columnName text not null,
$Category_columnParentIn integer); $Category_columnParentIn integer,
$Category_columnAppCompanyId integer
);
'''); ''');
//Service
await db.execute(''' await db.execute('''
CREATE TABLE IF NOT EXISTS $Service_tableName ( CREATE TABLE IF NOT EXISTS $Service_tableName (
$Service_columnId integer primary key unique, $Service_columnId integer primary key unique,
$Service_columnArticul integer not null, $Service_columnArticul integer not null,
$Service_columnName text not null, $Service_columnName text not null,
$Service_columnPrice real not null); $Service_columnPrice real not null,
$Service_columnAppCompanyId integer,
$Service_columnDescription text,
$Service_columnShowPrice real,
$Service_columnOkei text,
$Service_columnDiscount real
);
'''); ''');
} }

View File

@ -1,8 +1,8 @@
import 'package:aman_kassa_flutter/core/base/base_service.dart'; import 'package:aman_kassa_flutter/core/base/base_service.dart';
import 'package:aman_kassa_flutter/core/models/Message.dart'; import 'package:aman_kassa_flutter/core/models/message.dart';
import 'package:aman_kassa_flutter/core/models/Response.dart'; import 'package:aman_kassa_flutter/core/models/response.dart';
import 'package:aman_kassa_flutter/core/models/user.dart'; import 'package:aman_kassa_flutter/core/models/user.dart';
import 'package:aman_kassa_flutter/core/models/authResponse.dart'; import 'package:aman_kassa_flutter/core/models/auth_response.dart';
import 'package:flutter/foundation.dart'; import 'package:flutter/foundation.dart';
import 'ApiService.dart'; import 'ApiService.dart';

View File

@ -6,18 +6,20 @@ import 'package:flutter/cupertino.dart';
class DialogService { class DialogService {
GlobalKey<NavigatorState> _dialogNavigationKey = GlobalKey<NavigatorState>(); GlobalKey<NavigatorState> _dialogNavigationKey = GlobalKey<NavigatorState>();
Function(DialogRequest) _showDialogListener; Function(DialogRequest) _showDialogListener;
Function(DialogRequest) _showDialogInputListener;
Completer<DialogResponse> _dialogCompleter; Completer<DialogResponse> _dialogCompleter;
GlobalKey<NavigatorState> get dialogNavigationKey => _dialogNavigationKey; GlobalKey<NavigatorState> get dialogNavigationKey => _dialogNavigationKey;
/// Registers a callback function. Typically to show the dialog /// Registers a callback function. Typically to show the dialog
void registerDialogListener(Function(DialogRequest) showDialogListener) { void registerDialogListener(Function(DialogRequest) showDialogListener, Function(DialogRequest) showDialogInputListener) {
_showDialogListener = showDialogListener; _showDialogListener = showDialogListener;
_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, String title = 'Aman Касса',
String description, String description,
String buttonTitle = 'Ok', String buttonTitle = 'Ok',
}) { }) {
@ -45,6 +47,20 @@ class DialogService {
return _dialogCompleter.future; return _dialogCompleter.future;
} }
Future<DialogResponse> showConfirmationDialogInput(
{String title =' Aman Касса',
String description,
String confirmationTitle = 'Ok',
String cancelTitle = 'Cancel'}) {
_dialogCompleter = Completer<DialogResponse>();
_showDialogInputListener(DialogRequest(
title: title,
description: description,
buttonTitle: confirmationTitle,
cancelTitle: cancelTitle));
return _dialogCompleter.future;
}
/// Completes the _dialogCompleter to resume the Future's execution call /// Completes the _dialogCompleter to resume the Future's execution call
void dialogComplete(DialogResponse response) { void dialogComplete(DialogResponse response) {
_dialogNavigationKey.currentState.pop(); _dialogNavigationKey.currentState.pop();

4
lib/core/utilsParse.dart Normal file
View File

@ -0,0 +1,4 @@
List<String> parseListString(json){
if(json==null) return null;
return new List<String>.from(json);
}

View File

@ -0,0 +1,49 @@
import 'dart:convert';
import 'package:aman_kassa_flutter/core/entity/Category.dart';
import 'package:aman_kassa_flutter/core/entity/Goods.dart';
import 'package:aman_kassa_flutter/core/locator.dart';
import 'package:aman_kassa_flutter/core/models/dict_dao.dart';
import 'package:aman_kassa_flutter/core/models/product_dao.dart';
import 'package:aman_kassa_flutter/core/models/response.dart';
import 'package:aman_kassa_flutter/core/models/smena.dart';
import 'package:aman_kassa_flutter/core/services/ApiService.dart';
import 'package:aman_kassa_flutter/core/services/DataService.dart';
import 'package:aman_kassa_flutter/core/services/navigator_service.dart';
import 'package:aman_kassa_flutter/redux/constants/setting_const.dart';
import 'package:aman_kassa_flutter/redux/state/calc_state.dart';
import 'package:aman_kassa_flutter/redux/state/kassa_state.dart';
import 'package:aman_kassa_flutter/redux/state/setting_state.dart';
import 'package:aman_kassa_flutter/widgets/components/calculator/calculator.dart';
import 'package:meta/meta.dart';
import 'package:redux/redux.dart';
import 'package:redux_thunk/redux_thunk.dart';
import '../store.dart';
@immutable
class SetCalcStateAction {
final CalcState calcState;
SetCalcStateAction(this.calcState);
}
Future<void> setEqual(Store<AppState> store) async {
store.dispatch(SetCalcStateAction(CalcState(isEqual: true)));
}
ThunkAction<AppState> onTapAction(String value) {
return (Store<AppState> store) async {
if(value == Calculations.EQUAL){
return setEqual(store);
}
//TODO create private methods by operations and values
List calcItems = Calculator.action(value: value, items: store.state.calcState.calcItems);
calcItems.asMap().forEach((index,element ) {
print('#$index: ${element.toString()}');
});
store.dispatch(SetCalcStateAction(CalcState(calcItems: calcItems, isEqual: false)));
};
}

View File

@ -0,0 +1,136 @@
import 'dart:convert';
import 'package:aman_kassa_flutter/core/entity/Category.dart';
import 'package:aman_kassa_flutter/core/entity/Goods.dart';
import 'package:aman_kassa_flutter/core/entity/Service.dart';
import 'package:aman_kassa_flutter/core/locator.dart';
import 'package:aman_kassa_flutter/core/models/dict_dao.dart';
import 'package:aman_kassa_flutter/core/models/product_dao.dart';
import 'package:aman_kassa_flutter/core/models/response.dart';
import 'package:aman_kassa_flutter/core/models/smena.dart';
import 'package:aman_kassa_flutter/core/services/ApiService.dart';
import 'package:aman_kassa_flutter/core/services/DataService.dart';
import 'package:aman_kassa_flutter/core/services/navigator_service.dart';
import 'package:aman_kassa_flutter/redux/constants/setting_const.dart';
import 'package:aman_kassa_flutter/redux/state/kassa_state.dart';
import 'package:meta/meta.dart';
import 'package:redux/redux.dart';
import 'package:redux_thunk/redux_thunk.dart';
import '../store.dart';
@immutable
class SetKassaStateAction {
final KassaState kassaState;
SetKassaStateAction(this.kassaState);
}
final ApiService _api = locator<ApiService>();
final DataService _dataService = locator<DataService>();
final NavigatorService _navigation = locator<NavigatorService>();
Future<void> backBottomElement(Store<AppState> store) async {
List<DictDao> prevCategories = store.state.kassaState.prevCategories;
DictDao last = prevCategories.removeLast();
if (last != null) {
store.dispatch(SetKassaStateAction(KassaState(prevCategories: prevCategories)));
store.dispatch(selectBottomElement(last.id));
}
}
ThunkAction<AppState> addCustomProductToKassaItems(String name, int count, double price, double total) {
return (Store<AppState> store) async {
List<ProductDao> items = store.state.kassaState.kassaItems;
items.add(new ProductDao(name: name, count: count, price: price, total: total));
store.dispatch(SetKassaStateAction(KassaState(kassaItems: items)));
};
}
ThunkAction<AppState> addProductToKassaItems(Good good) {
return (Store<AppState> store) async {
List<ProductDao> items = store.state.kassaState.kassaItems;
int index = items.indexWhere((element) => element.good?.id == good.id);
if (index > -1) {
store.dispatch(counterProductFromKassaItems(index, 1));
} else {
items.add(new ProductDao(
name: good.name, good: good, count: 1, price: good.price, total: good.price));
store.dispatch(SetKassaStateAction(KassaState(kassaItems: items)));
}
};
}
ThunkAction<AppState> addServiceToKassaItems(Service service) {
return (Store<AppState> store) async {
List<ProductDao> items = store.state.kassaState.kassaItems;
int index = items.indexWhere((element) => element.good?.id == service.id);
if (index > -1) {
store.dispatch(counterProductFromKassaItems(index, 1));
} else {
items.add(new ProductDao(
name: service.name, service: service, count: 1, price: service.price, total: service.price));
store.dispatch(SetKassaStateAction(KassaState(kassaItems: items)));
}
};
}
ThunkAction<AppState> removeProductFromKassaItems(int index) {
return (Store<AppState> store) async {
List<ProductDao> items = List.from(store.state.kassaState.kassaItems);
items.removeAt(index);
store.dispatch(SetKassaStateAction(KassaState(kassaItems: items)));
};
}
ThunkAction<AppState> counterProductFromKassaItems(int index, int counter) {
return (Store<AppState> store) async {
List<ProductDao> items = store.state.kassaState.kassaItems;
ProductDao product = items.elementAt(index);
if (product.count == 1 && counter < 0) {
//if count to zero need delete element
store.dispatch(removeProductFromKassaItems(index));
} else {
product.count += counter;
product.total = (((product.count * product.price) * 100).roundToDouble()) / 100;
store.dispatch(SetKassaStateAction(KassaState(kassaItems: items)));
}
};
}
ThunkAction<AppState> selectBottomElement(int parentId) {
return (Store<AppState> store) async {
store.dispatch(SetKassaStateAction(KassaState(bottomSheetLoading: true)));
try {
List<DictDao> prevCategories = store.state.kassaState.prevCategories;
if (parentId == 0) {
prevCategories = [];
}
store.state.kassaState.bottomSheetElements.forEach((element) {
if (element is Category && element.id == parentId) {
prevCategories.add(DictDao(id: element.parentIn, name: element.name));
}
});
List _bottomSheetElements = [];
if(store.state.settingState.tradeType == SettingTradeTypeGood) {
List<Category> categories = await _dataService.getCategoriesByParentId(parentId: parentId);
_bottomSheetElements.addAll(categories);
List<Good> goods = await _dataService.getGoodsByCategoryId(categoryId: parentId);
_bottomSheetElements.addAll(goods);
} else if(store.state.settingState.tradeType == SettingTradeTypeService) {
List<Service> services = await _dataService.getServices();
_bottomSheetElements.addAll(services);
}
store.dispatch(SetKassaStateAction(KassaState(
bottomSheetLoading: false,
bottomSheetElements: _bottomSheetElements,
prevCategories: prevCategories)));
} catch (e) {
print(e);
store.dispatch(SetKassaStateAction(KassaState(bottomSheetLoading: false)));
}
};
}

View File

@ -1,112 +0,0 @@
import 'dart:convert';
import 'package:aman_kassa_flutter/core/entity/Category.dart';
import 'package:aman_kassa_flutter/core/entity/Goods.dart';
import 'package:aman_kassa_flutter/core/locator.dart';
import 'package:aman_kassa_flutter/core/models/DictDao.dart';
import 'package:aman_kassa_flutter/core/models/ProductDao.dart';
import 'package:aman_kassa_flutter/core/services/ApiService.dart';
import 'package:aman_kassa_flutter/core/services/DataService.dart';
import 'package:aman_kassa_flutter/core/services/navigator_service.dart';
import 'package:aman_kassa_flutter/redux/state/main_state.dart';
import 'package:meta/meta.dart';
import 'package:redux/redux.dart';
import 'package:redux_thunk/redux_thunk.dart';
import '../store.dart';
@immutable
class SetMainStateAction {
final MainState mainState;
SetMainStateAction(this.mainState);
}
final ApiService _api = locator<ApiService>();
final DataService _dataService = locator<DataService>();
final NavigatorService _navigation = locator<NavigatorService>();
Future<void> backBottomElement(Store<AppState> store) async {
List<DictDao> prevCategories = store.state.mainState.prevCategories;
DictDao last = prevCategories.removeLast();
if (last != null) {
store.dispatch(
SetMainStateAction(MainState(prevCategories: prevCategories)));
store.dispatch(selectBottomElement(last.id));
}
}
ThunkAction<AppState> addCustomProductToKassaItems(String name, int count, double price) {
return (Store<AppState> store) async {
List<ProductDao> items = store.state.mainState.kassaItems;
items.add(new ProductDao(name: name, count: count, price: price));
store.dispatch(SetMainStateAction(MainState(kassaItems: items)));
};
}
ThunkAction<AppState> addProductToKassaItems(Good good) {
return (Store<AppState> store) async {
List<ProductDao> items = store.state.mainState.kassaItems;
int index = items.indexWhere((element) => element.good?.id == good.id);
if (index > -1) {
store.dispatch(counterProductFromKassaItems(index, 1));
} else {
items.add(new ProductDao(
name: good.name, good: good, count: 1, price: good.price));
store.dispatch(SetMainStateAction(MainState(kassaItems: items)));
}
};
}
ThunkAction<AppState> removeProductFromKassaItems(int index) {
return (Store<AppState> store) async {
List<ProductDao> items = List.from(store.state.mainState.kassaItems);
items.removeAt(index);
store.dispatch(SetMainStateAction(MainState(kassaItems: items)));
};
}
ThunkAction<AppState> counterProductFromKassaItems(int index, int counter) {
return (Store<AppState> store) async {
List<ProductDao> items = store.state.mainState.kassaItems;
if (items.elementAt(index).count == 1 && counter < 0) {
//if count to zero need delete element
store.dispatch(removeProductFromKassaItems(index));
} else {
items.elementAt(index).count += counter;
store.dispatch(SetMainStateAction(MainState(kassaItems: items)));
}
};
}
ThunkAction<AppState> selectBottomElement(int parentId) {
return (Store<AppState> store) async {
store.dispatch(SetMainStateAction(MainState(bottomSheetLoading: true)));
try {
List<DictDao> prevCategories = store.state.mainState.prevCategories;
if (parentId == 0) {
prevCategories = [];
}
store.state.mainState.bottomSheetElements.forEach((element) {
if (element is Category && element.id == parentId) {
prevCategories.add(DictDao(id: element.parentIn, name: element.name));
}
});
List<Category> categories =
await _dataService.getCategoriesByParentId(parentId: parentId);
List<Good> goods =
await _dataService.getGoodsByCategoryId(categoryId: parentId);
List _bottomSheetElements = [];
_bottomSheetElements.addAll(categories);
_bottomSheetElements.addAll(goods);
store.dispatch(SetMainStateAction(MainState(
bottomSheetLoading: false,
bottomSheetElements: _bottomSheetElements,
prevCategories: prevCategories)));
} catch (e) {
print(e);
store.dispatch(SetMainStateAction(MainState(bottomSheetLoading: false)));
}
};
}

View File

@ -0,0 +1,39 @@
import 'dart:convert';
import 'package:aman_kassa_flutter/core/entity/Category.dart';
import 'package:aman_kassa_flutter/core/entity/Goods.dart';
import 'package:aman_kassa_flutter/core/locator.dart';
import 'package:aman_kassa_flutter/core/models/dict_dao.dart';
import 'package:aman_kassa_flutter/core/models/product_dao.dart';
import 'package:aman_kassa_flutter/core/models/response.dart';
import 'package:aman_kassa_flutter/core/models/smena.dart';
import 'package:aman_kassa_flutter/core/services/ApiService.dart';
import 'package:aman_kassa_flutter/core/services/DataService.dart';
import 'package:aman_kassa_flutter/core/services/navigator_service.dart';
import 'package:aman_kassa_flutter/redux/constants/setting_const.dart';
import 'package:aman_kassa_flutter/redux/state/kassa_state.dart';
import 'package:aman_kassa_flutter/redux/state/setting_state.dart';
import 'package:meta/meta.dart';
import 'package:redux/redux.dart';
import 'package:redux_thunk/redux_thunk.dart';
import '../store.dart';
@immutable
class SetSettingStateAction {
final SettingState settingState;
SetSettingStateAction(this.settingState);
}
ThunkAction<AppState> changeModeFromSetting(bool isKassa) {
return (Store<AppState> store) async {
store.dispatch(SetSettingStateAction(SettingState(mode: isKassa? SettingModeKassa: SettingModeCalc )));
};
}
ThunkAction<AppState> changeTradeTypeFromSetting(String tradeType) {
return (Store<AppState> store) async {
store.dispatch(SetSettingStateAction(SettingState(tradeType: tradeType )));
};
}

View File

@ -1,9 +1,10 @@
import 'dart:convert'; import 'dart:convert';
import 'package:aman_kassa_flutter/core/locator.dart'; import 'package:aman_kassa_flutter/core/locator.dart';
import 'package:aman_kassa_flutter/core/models/Message.dart'; import 'package:aman_kassa_flutter/core/models/message.dart';
import 'package:aman_kassa_flutter/core/models/authResponse.dart'; import 'package:aman_kassa_flutter/core/models/auth_response.dart';
import 'package:aman_kassa_flutter/core/models/Response.dart'; import 'package:aman_kassa_flutter/core/models/response.dart';
import 'package:aman_kassa_flutter/core/models/smena.dart';
import 'package:aman_kassa_flutter/core/models/user.dart'; import 'package:aman_kassa_flutter/core/models/user.dart';
import 'package:aman_kassa_flutter/core/route_names.dart'; import 'package:aman_kassa_flutter/core/route_names.dart';
import 'package:aman_kassa_flutter/core/services/ApiService.dart'; import 'package:aman_kassa_flutter/core/services/ApiService.dart';
@ -53,7 +54,7 @@ ThunkAction<AppState> authenticate(String email, String password) {
return (Store<AppState> store) async { return (Store<AppState> store) async {
store.dispatch(SetUserStateAction(UserState(isLoading: true))); store.dispatch(SetUserStateAction(UserState(isLoading: true)));
try { try {
AuthBody result = await _api.authenticate(email, password); AuthBody result = await _api.authenticate(email, password, statusCheck: false);
store.dispatch(SetUserStateAction(UserState( store.dispatch(SetUserStateAction(UserState(
isLoading: false, isLoading: false,
loginFormMessage: LoginFormMessage(email: result.email?.join(","), password: result.password?.join(","), message: result.message), loginFormMessage: LoginFormMessage(email: result.email?.join(","), password: result.password?.join(","), message: result.message),
@ -66,7 +67,29 @@ ThunkAction<AppState> authenticate(String email, String password) {
_navigation.replace(HomeViewRoute); _navigation.replace(HomeViewRoute);
} }
} catch(e) { } catch(e) {
print(e);
store.dispatch(SetUserStateAction(UserState(isLoading: false))); store.dispatch(SetUserStateAction(UserState(isLoading: false)));
} }
}; };
} }
Future<void> checkSmena(Store<AppState> store) async {
String token = store.state.userState.user.token;
Response<Smena> result = await _api.smena(token);
store.dispatch(SetUserStateAction(UserState(smena: result.body)));
}
Future<void> closeSmena(Store<AppState> store) async {
String token = store.state.userState.user.token;
Response<Smena> result = await _api.closeSmena(token);
store.dispatch(SetUserStateAction(UserState(smena: result.body)));
}
Future<void> openSmena(Store<AppState> store) async {
String token = store.state.userState.user.token;
Response<Smena> result = await _api.openSmena(token);
store.dispatch(SetUserStateAction(UserState(smena: result.body)));
if(result.operation){
store.dispatch(checkSmena);
}
}

View File

@ -0,0 +1,2 @@
const String OperationTypePay = 'OperationTypePay';
const String OperationTypeReturn = 'OperationTypeReturn';

View File

@ -0,0 +1,6 @@
const String SettingModeKassa = 'kassaMode';
const String SettingModeCalc = 'calcMode';
const String SettingTradeTypeGood = 'g';
const String SettingTradeTypeService = 's';

View File

@ -0,0 +1,10 @@
import 'package:aman_kassa_flutter/redux/actions/calc_actions.dart';
import 'package:aman_kassa_flutter/redux/state/calc_state.dart';
calcReducer(CalcState prevState, SetCalcStateAction action) {
final payload = action.calcState;
return prevState.copyWith(
calcItems: payload.calcItems,
isEqual: payload.isEqual
);
}

View File

@ -1,8 +1,8 @@
import 'package:aman_kassa_flutter/redux/actions/main_actions.dart'; import 'package:aman_kassa_flutter/redux/actions/kassa_actions.dart';
import 'package:aman_kassa_flutter/redux/state/main_state.dart'; import 'package:aman_kassa_flutter/redux/state/kassa_state.dart';
mainReducer(MainState prevState, SetMainStateAction action) { mainReducer(KassaState prevState, SetKassaStateAction action) {
final payload = action.mainState; final payload = action.kassaState;
return prevState.copyWith( return prevState.copyWith(
bottomSheetElements: payload.bottomSheetElements, bottomSheetElements: payload.bottomSheetElements,
bottomSheetLoading: payload.bottomSheetLoading, bottomSheetLoading: payload.bottomSheetLoading,

View File

@ -0,0 +1,12 @@
import 'package:aman_kassa_flutter/redux/actions/kassa_actions.dart';
import 'package:aman_kassa_flutter/redux/actions/setting_actions.dart';
import 'package:aman_kassa_flutter/redux/state/kassa_state.dart';
import 'package:aman_kassa_flutter/redux/state/setting_state.dart';
settingReducer(SettingState prevState, SetSettingStateAction action) {
final payload = action.settingState;
return prevState.copyWith(
mode: payload.mode,
tradeType: payload.tradeType
);
}

View File

@ -10,5 +10,6 @@ userReducer(UserState prevState, SetUserStateAction action) {
user: payload.user, user: payload.user,
isAuthenticated: payload.isAuthenticated, isAuthenticated: payload.isAuthenticated,
loginFormMessage: payload.loginFormMessage, loginFormMessage: payload.loginFormMessage,
smena: payload.smena,
); );
} }

View File

@ -0,0 +1,26 @@
import 'dart:collection';
import 'package:aman_kassa_flutter/core/models/calc_model.dart';
import 'package:aman_kassa_flutter/redux/constants/setting_const.dart';
import 'package:meta/meta.dart';
@immutable
class CalcState {
final List<CalcModel> calcItems;
final bool isEqual;
CalcState({this.calcItems, this.isEqual});
factory CalcState.initial() => CalcState(calcItems: [], isEqual: false);
CalcState copyWith({
@required calcItems,
@required isEqual,
}) {
return CalcState(
calcItems: calcItems ?? this.calcItems,
isEqual: isEqual ?? this.isEqual,
);
}
}

View File

@ -1,35 +1,37 @@
import 'package:aman_kassa_flutter/core/models/DictDao.dart'; import 'package:aman_kassa_flutter/core/models/dict_dao.dart';
import 'package:aman_kassa_flutter/core/models/ProductDao.dart'; import 'package:aman_kassa_flutter/core/models/product_dao.dart';
import 'package:aman_kassa_flutter/core/models/smena.dart';
import 'package:meta/meta.dart'; import 'package:meta/meta.dart';
@immutable @immutable
class MainState { class KassaState {
final List bottomSheetElements; final List bottomSheetElements;
final bool bottomSheetLoading; final bool bottomSheetLoading;
final List<DictDao> prevCategories; final List<DictDao> prevCategories;
final List<ProductDao> kassaItems; final List<ProductDao> kassaItems;
MainState(
KassaState(
{this.bottomSheetElements, {this.bottomSheetElements,
this.bottomSheetLoading, this.bottomSheetLoading,
this.prevCategories, this.prevCategories,
this.kassaItems}); this.kassaItems,
});
factory MainState.initial() => MainState( factory KassaState.initial() => KassaState(
bottomSheetElements: [], bottomSheetElements: [],
bottomSheetLoading: false, bottomSheetLoading: false,
prevCategories: [], prevCategories: [],
kassaItems: [], kassaItems: [],
); );
MainState copyWith({ KassaState copyWith({
@required bottomSheetElements, @required bottomSheetElements,
@required bottomSheetLoading, @required bottomSheetLoading,
@required prevCategories, @required prevCategories,
@required kassaItems, @required kassaItems,
}) { }) {
return MainState( return KassaState(
bottomSheetElements: bottomSheetElements ?? this.bottomSheetElements, bottomSheetElements: bottomSheetElements ?? this.bottomSheetElements,
bottomSheetLoading: bottomSheetLoading ?? this.bottomSheetLoading, bottomSheetLoading: bottomSheetLoading ?? this.bottomSheetLoading,
prevCategories: prevCategories ?? this.prevCategories, prevCategories: prevCategories ?? this.prevCategories,

View File

@ -0,0 +1,22 @@
import 'package:aman_kassa_flutter/redux/constants/setting_const.dart';
import 'package:meta/meta.dart';
@immutable
class SettingState {
final String mode;
final String tradeType;
SettingState({this.mode, this.tradeType});
factory SettingState.initial() => SettingState(mode: SettingModeCalc, tradeType: SettingTradeTypeGood);
SettingState copyWith({
@required mode,
@required tradeType,
}) {
return SettingState(
mode: mode ?? this.mode,
tradeType: tradeType ?? this.tradeType,
);
}
}

View File

@ -1,3 +1,4 @@
import 'package:aman_kassa_flutter/core/models/smena.dart';
import 'package:aman_kassa_flutter/core/models/user.dart'; import 'package:aman_kassa_flutter/core/models/user.dart';
import 'package:meta/meta.dart'; import 'package:meta/meta.dart';
@ -8,13 +9,15 @@ class UserState {
final bool isAuthenticated; final bool isAuthenticated;
final LoginFormMessage loginFormMessage; final LoginFormMessage loginFormMessage;
final User user; final User user;
final Smena smena;
UserState({ UserState({
this.isError, this.isError,
this.isLoading, this.isLoading,
this.isAuthenticated, this.isAuthenticated,
this.user, this.user,
this.loginFormMessage this.loginFormMessage,
this.smena
}); });
factory UserState.initial() => UserState( factory UserState.initial() => UserState(
@ -22,6 +25,7 @@ class UserState {
isError: false, isError: false,
isAuthenticated: false, isAuthenticated: false,
loginFormMessage: LoginFormMessage(), loginFormMessage: LoginFormMessage(),
smena: Smena(),
); );
UserState copyWith({ UserState copyWith({
@ -30,6 +34,7 @@ class UserState {
@required User user, @required User user,
@required bool isAuthenticated, @required bool isAuthenticated,
@required LoginFormMessage loginFormMessage, @required LoginFormMessage loginFormMessage,
@required Smena smena,
}) { }) {
return UserState( return UserState(
isError: isError ?? this.isError, isError: isError ?? this.isError,
@ -37,6 +42,7 @@ class UserState {
isAuthenticated: isAuthenticated ?? this.isAuthenticated, isAuthenticated: isAuthenticated ?? this.isAuthenticated,
user: user ?? this.user, user: user ?? this.user,
loginFormMessage: loginFormMessage ?? this.loginFormMessage, loginFormMessage: loginFormMessage ?? this.loginFormMessage,
smena: smena ?? this.smena,
); );
} }
} }

View File

@ -1,23 +1,38 @@
import 'package:aman_kassa_flutter/redux/actions/main_actions.dart'; import 'package:aman_kassa_flutter/redux/actions/kassa_actions.dart';
import 'package:aman_kassa_flutter/redux/actions/setting_actions.dart';
import 'package:aman_kassa_flutter/redux/actions/user_actions.dart'; import 'package:aman_kassa_flutter/redux/actions/user_actions.dart';
import 'package:aman_kassa_flutter/redux/reducers/calc_reducer.dart';
import 'package:aman_kassa_flutter/redux/reducers/main_reducer.dart'; import 'package:aman_kassa_flutter/redux/reducers/main_reducer.dart';
import 'package:aman_kassa_flutter/redux/reducers/setting_reducer.dart';
import 'package:aman_kassa_flutter/redux/reducers/user_reducer.dart'; import 'package:aman_kassa_flutter/redux/reducers/user_reducer.dart';
import 'package:aman_kassa_flutter/redux/state/main_state.dart'; import 'package:aman_kassa_flutter/redux/state/calc_state.dart';
import 'package:aman_kassa_flutter/redux/state/kassa_state.dart';
import 'package:aman_kassa_flutter/redux/state/setting_state.dart';
import 'package:aman_kassa_flutter/redux/state/user_state.dart'; import 'package:aman_kassa_flutter/redux/state/user_state.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 'actions/calc_actions.dart';
//reducer context //reducer context
AppState appReducer(AppState state, dynamic action) { AppState appReducer(AppState state, dynamic action) {
if (action is SetUserStateAction) {
if (action is SetUserStateAction) { /** UserAction **/ /** UserAction **/
final nextUserState = userReducer(state.userState, action); final nextUserState = userReducer(state.userState, action);
return state.copyWith(userState: nextUserState); return state.copyWith(userState: nextUserState);
} else if(action is SetMainStateAction) { /** MainAction **/ } else if (action is SetKassaStateAction) {
final nextMainState = mainReducer(state.mainState, action); /** KassaAction **/
return state.copyWith(mainState: nextMainState); final nextMainState = mainReducer(state.kassaState, action);
return state.copyWith(kassaState: nextMainState);
} else if (action is SetSettingStateAction) {
/** SettingAction **/
final nextSettingState = settingReducer(state.settingState, action);
return state.copyWith(settingState: nextSettingState);
} else if (action is SetCalcStateAction) {
/** CalcAction **/
final nextCalcState = calcReducer(state.calcState, action);
return state.copyWith(calcState: nextCalcState);
} }
return state; return state;
} }
@ -26,20 +41,29 @@ AppState appReducer(AppState state, dynamic action) {
@immutable @immutable
class AppState { class AppState {
final UserState userState; final UserState userState;
final MainState mainState; final KassaState kassaState;
final SettingState settingState;
final CalcState calcState;
AppState({ AppState({
@required this.userState, @required this.userState,
@required this.mainState, @required this.kassaState,
@required this.settingState,
@required this.calcState,
}); });
//stable work //stable work
AppState copyWith({ AppState copyWith({
UserState userState, UserState userState,
MainState mainState, KassaState kassaState,
SettingState settingState,
CalcState calcState,
}) { }) {
return AppState( return AppState(
userState: userState ?? this.userState, userState: userState ?? this.userState,
mainState: mainState ?? this.mainState, kassaState: kassaState ?? this.kassaState,
settingState: settingState ?? this.settingState,
calcState: calcState ?? this.calcState,
); );
} }
} }
@ -58,12 +82,18 @@ class Redux {
//initial context //initial context
static Future<void> init() async { static Future<void> init() async {
final userStateInitial = UserState.initial(); final userStateInitial = UserState.initial();
final mainStateInitial = MainState.initial(); final kassaStateInitial = KassaState.initial();
final settingStateInitial = SettingState.initial();
final calcStateInitial = CalcState.initial();
_store = Store<AppState>( _store = Store<AppState>(
appReducer, appReducer,
middleware: [thunkMiddleware], middleware: [thunkMiddleware],
initialState: AppState(userState: userStateInitial, mainState: mainStateInitial), initialState: AppState(
userState: userStateInitial,
kassaState: kassaStateInitial,
settingState: settingStateInitial,
calcState: calcStateInitial),
); );
} }
} }

View File

@ -24,10 +24,10 @@ const TextStyle productTextStyle = const TextStyle(fontWeight: FontWeight.w400,
const TextStyle buttonTitleTextStyle = const TextStyle(fontWeight: FontWeight.w700, color: whiteColor, fontSize: 15); const TextStyle buttonTitleTextStyle = const TextStyle(fontWeight: FontWeight.w700, color: whiteColor, fontSize: 15);
const TextStyle buttonBigTitleTextStyle = const TextStyle(fontWeight: FontWeight.w700, color: whiteColor, fontSize: 22, ); const TextStyle buttonBigTitleTextStyle = const TextStyle(fontWeight: FontWeight.w700, color: whiteColor, fontSize: 22, );
const TextStyle stepTitleTextStyle = const TextStyle dropDownTradeTypeTextStyle = TextStyle( color: Colors.black54, fontWeight: FontWeight.bold, fontSize: 24);
const TextStyle(fontWeight: FontWeight.w700, color: textColor, fontSize: 15);
const TextStyle stepSubTitleTextStyle = const TextStyle(fontWeight: FontWeight.w400, color: textColor, fontSize: 12);
// Box Shadow // Box Shadow
const BoxShadow mainShadowBox = BoxShadow(blurRadius: 16, color: shadowColor, offset: Offset(0, 5)); const BoxShadow mainShadowBox = BoxShadow(blurRadius: 16, color: shadowColor, offset: Offset(0, 5));
const BoxShadow cardShadowBox = BoxShadow(blurRadius: 23, color: cardShadowColor, offset: Offset(0, 2)); const BoxShadow buttonShadowBox = BoxShadow(blurRadius: 5, color: Colors.grey, offset: Offset(0, 1));
const BoxShadow cardShadowBox = BoxShadow(blurRadius: 5, color: Colors.black26, offset: Offset(0, 5));

View File

@ -0,0 +1,36 @@
import 'dart:convert';
import 'package:aman_kassa_flutter/shared/app_colors.dart';
import 'package:flutter/material.dart';
class ImageShowContainer extends StatelessWidget {
final ImageShowModel data;
ImageShowContainer(this.data);
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
//backgroundColor: fillColor,
title: Text(data.title),
),
body: ListView(
children: <Widget>[
imageFromBase64String(data.data)
],
),
);
}
}
Padding imageFromBase64String(String base64String) {
return Padding(
padding: const EdgeInsets.symmetric(vertical: 10.0, horizontal: 8.0),
child: Image.memory(base64Decode(base64String)),
);
}
class ImageShowModel {
final String data;
final String title;
ImageShowModel(this.data, this.title);
}

View File

@ -0,0 +1,61 @@
import 'package:aman_kassa_flutter/redux/constants/setting_const.dart';
import 'package:aman_kassa_flutter/redux/state/setting_state.dart';
import 'package:aman_kassa_flutter/redux/store.dart';
import 'package:aman_kassa_flutter/shared/app_colors.dart';
import 'package:flutter/material.dart';
import 'package:flutter_redux/flutter_redux.dart';
import 'package:material_design_icons_flutter/material_design_icons_flutter.dart';
class BottomBar extends StatelessWidget {
final PageController pageController;
final int selectedTabIndex;
BottomBar({
this.pageController,
this.selectedTabIndex,
});
@override
Widget build(BuildContext context) {
return StoreConnector<AppState, SettingState>(
converter: (store) => store.state.settingState,
builder: (context, vm) {
return BottomNavigationBar(
currentIndex: selectedTabIndex,
backgroundColor: menuColor,
type: BottomNavigationBarType.shifting,
items: [
vm.mode == SettingModeKassa
? BottomNavigationBarItem(
backgroundColor: menuColor,
icon: Icon(MdiIcons.cashRegister, color: Colors.white),
title: new Text(
'Касса',
style: TextStyle(color: Colors.white),
))
: BottomNavigationBarItem(
backgroundColor: menuColor,
icon: Icon(MdiIcons.calculator, color: Colors.white),
title: new Text(
'Калькулятор',
style: TextStyle(color: Colors.white),
)),
BottomNavigationBarItem(
backgroundColor: menuColor,
icon: Icon(MdiIcons.tune, color: Colors.white),
title: new Text(
'Опции',
style: TextStyle(color: Colors.white),
)),
],
onTap: (index) {
pageController.animateToPage(
index,
duration: const Duration(milliseconds: 300),
curve: Curves.easeIn,
);
},
);
});
}
}

View File

@ -0,0 +1,44 @@
import 'package:aman_kassa_flutter/redux/state/user_state.dart';
import 'package:aman_kassa_flutter/redux/store.dart';
import 'package:aman_kassa_flutter/shared/app_colors.dart';
import 'package:flutter/material.dart';
import 'package:flutter_redux/flutter_redux.dart';
import 'package:intl/intl.dart';
DateFormat dateFormat = DateFormat("yyyy-MM-dd HH:mm:ss");
class HeaderTitle extends StatelessWidget {
@override
Widget build(BuildContext context) {
return StoreConnector<AppState, UserState>(
converter: (store) => store.state.userState,
builder: (context, vm) {
return Row(
children: <Widget>[
Container(
width: 75,
child: Image(
image: AssetImage('assets/images/logo.png'),
fit: BoxFit.fitWidth,
),
margin: const EdgeInsets.only(right: 15),
),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text('Пользователь: ${vm.user.email}' ,style: TextStyle(fontSize: 13, color: Colors.black),),
vm.smena.message !=null
? Text(vm.smena.message, style: TextStyle(fontSize: 13, color: redColor) )
: vm.smena.startedAt !=null
? Text('Смена от: ${dateFormat.format(vm.smena.startedAt)}' , style: TextStyle(fontSize: 13, color: Colors.black),)
: Text('Смена от:', style: TextStyle(fontSize: 13, color: Colors.black),),
],
),
)
],
);
}
);
}
}

View File

@ -0,0 +1,40 @@
import 'package:aman_kassa_flutter/core/models/choice.dart';
import 'package:aman_kassa_flutter/shared/app_colors.dart';
import 'package:flutter/material.dart';
const List<Choice> choices = const <Choice>[
const Choice(title: 'Обновить номенклатуру', icon: Icons.update, command: 'update'),
const Choice(title: 'Помощь', icon: Icons.help, command: 'help'),
const Choice(title: 'О Программе', icon: Icons.info_outline, command: 'info'),
const Choice(title: 'Язык', icon: Icons.language, command: 'language'),
const Choice(title: 'Выйти', icon: Icons.exit_to_app, command: 'exit')
];
class PopupMenu extends StatelessWidget {
final void Function(Choice value) onSelectChoice;
PopupMenu({this.onSelectChoice});
@override
Widget build(BuildContext context) {
return PopupMenuButton<Choice>(
icon: Icon(
Icons.more_vert,
color: menuColor,
),
onSelected: onSelectChoice,
itemBuilder: (BuildContext context) {
return choices.map((Choice choice) {
return PopupMenuItem<Choice>(
value: choice,
child: Row(children: <Widget>[
Icon(choice.icon, color: primaryColor,),
Text(choice.title)
], ),
);
}).toList();
},
);
}
}

View File

@ -1,22 +1,29 @@
import 'package:aman_kassa_flutter/core/locator.dart'; import 'package:aman_kassa_flutter/core/locator.dart';
import 'package:aman_kassa_flutter/core/models/Choice.dart'; import 'package:aman_kassa_flutter/core/logger.dart';
import 'package:aman_kassa_flutter/core/models/choice.dart';
import 'package:aman_kassa_flutter/core/services/DataService.dart'; import 'package:aman_kassa_flutter/core/services/DataService.dart';
import 'package:aman_kassa_flutter/redux/actions/user_actions.dart';
import 'package:aman_kassa_flutter/redux/constants/setting_const.dart';
import 'package:aman_kassa_flutter/redux/state/setting_state.dart';
import 'package:aman_kassa_flutter/redux/store.dart'; import 'package:aman_kassa_flutter/redux/store.dart';
import 'package:aman_kassa_flutter/shared/app_colors.dart'; import 'package:aman_kassa_flutter/shared/app_colors.dart';
import 'package:aman_kassa_flutter/views/home/components/header_title.dart';
import 'package:aman_kassa_flutter/widgets/loader/Dialogs.dart'; import 'package:aman_kassa_flutter/widgets/loader/Dialogs.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:google_fonts/google_fonts.dart'; import 'package:flutter_redux/flutter_redux.dart';
import 'package:material_design_icons_flutter/material_design_icons_flutter.dart'; import 'package:logger/logger.dart';
import './tabs/KassaTab.dart'; import './tabs/KassaTab.dart';
import './tabs/AdditionalTab.dart'; import './tabs/AdditionalTab.dart';
import './tabs/CalculatorTab.dart'; import './tabs/CalculatorTab.dart';
import './components/popup_menu.dart';
import 'components/bottom_bar.dart';
const List<Choice> choices = const <Choice>[ const List<Choice> choices = const <Choice>[
const Choice(title: 'Обновить номенклатуру', icon: Icons.update, command: 'update'), const Choice(
title: 'Обновить номенклатуру', icon: Icons.update, command: 'update'),
const Choice(title: 'Помощь', icon: Icons.help, command: 'help'), const Choice(title: 'Помощь', icon: Icons.help, command: 'help'),
const Choice(title: 'О Программе', icon: Icons.info_outline, command: 'info'), const Choice(title: 'О Программе', icon: Icons.info_outline, command: 'info'),
const Choice(title: 'Язык', icon: Icons.language, command: 'language'), const Choice(title: 'Язык', icon: Icons.language, command: 'language'),
@ -29,18 +36,18 @@ class HomeView extends StatefulWidget {
} }
class _HomeViewState extends State<HomeView> { class _HomeViewState extends State<HomeView> {
Logger log = getLogger('HomeView');
PageController pageController; PageController pageController;
int selectedTabIndex; int selectedTabIndex;
DataService _dataService = locator<DataService>(); DataService _dataService = locator<DataService>();
final GlobalKey<State> _keyLoader = new GlobalKey<State>(); final GlobalKey<State> _keyLoader = new GlobalKey<State>();
@override @override
void initState() { void initState() {
// TODO: implement initState
super.initState(); super.initState();
selectedTabIndex = 0; selectedTabIndex = 0;
pageController = new PageController(initialPage: selectedTabIndex); pageController = new PageController(initialPage: selectedTabIndex);
Redux.store.dispatch(checkSmena);
} }
@override @override
@ -54,8 +61,8 @@ class _HomeViewState extends State<HomeView> {
} else if (choice.command == 'update') { } else if (choice.command == 'update') {
Dialogs.showLoadingDialog(context, _keyLoader); Dialogs.showLoadingDialog(context, _keyLoader);
bool result = await _dataService.getDataFromServer(Redux.store.state.userState.user.token); bool result = await _dataService.getDataFromServer(Redux.store.state.userState.user);
print('result: $result'); log.i('result: $result');
Navigator.of(_keyLoader.currentContext, rootNavigator: true).pop(); Navigator.of(_keyLoader.currentContext, rootNavigator: true).pop();
} }
} }
@ -64,37 +71,18 @@ class _HomeViewState extends State<HomeView> {
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Scaffold( return Scaffold(
appBar: AppBar( appBar: AppBar(
title: Center( title: HeaderTitle(),
child: Container(
width: 100,
child: Image(
image: AssetImage('assets/images/logo.png'),
fit: BoxFit.fitHeight,
),
)),
actions: <Widget>[ actions: <Widget>[
PopupMenuButton<Choice>( PopupMenu(
icon: Icon( onSelectChoice: _onSelectChoice,
Icons.more_vert,
color: menuColor,
),
onSelected: _onSelectChoice,
itemBuilder: (BuildContext context) {
return choices.map((Choice choice) {
return PopupMenuItem<Choice>(
value: choice,
child: Row(children: <Widget>[
Icon(choice.icon, color: primaryColor,),
Text(choice.title)
], ),
);
}).toList();
},
) )
], ],
backgroundColor: fillColor, backgroundColor: fillColor,
), ),
body: PageView( body:StoreConnector<AppState, SettingState>(
converter: (store) => store.state.settingState,
builder: (context, vm) {
return PageView(
onPageChanged: (index) { onPageChanged: (index) {
setState(() { setState(() {
selectedTabIndex = index; selectedTabIndex = index;
@ -102,43 +90,15 @@ class _HomeViewState extends State<HomeView> {
}, },
controller: pageController, controller: pageController,
children: <Widget>[ children: <Widget>[
KassaTab(0), vm.mode == SettingModeKassa ? KassaTab(0) : CalculatorTab(0),
CalculatorTab(1), AdditionalTab(1),
AdditionalTab(2),
], ],
),
bottomNavigationBar: BottomNavigationBar(
currentIndex: selectedTabIndex,
backgroundColor: menuColor,
type: BottomNavigationBarType.shifting,
items: [
BottomNavigationBarItem(
backgroundColor: menuColor,
icon: Icon(MdiIcons.cashRegister, color: Colors.white),
title: new Text(
'Касса',
style: TextStyle(color: Colors.white),
)),
BottomNavigationBarItem(
icon: Icon(MdiIcons.calculator, color: Colors.white),
title: new Text(
'Калькулятор',
style: TextStyle(color: Colors.white),
)),
BottomNavigationBarItem(
icon: Icon(MdiIcons.tune, color: Colors.white),
title: new Text(
'Опции',
style: TextStyle(color: Colors.white),
)),
],
onTap: (index) {
pageController.animateToPage(
index,
duration: const Duration(milliseconds: 300),
curve: Curves.easeIn,
); );
}, }
),
bottomNavigationBar: BottomBar(
pageController: pageController,
selectedTabIndex: selectedTabIndex,
), ),
); );
} }

View File

@ -1,59 +1,298 @@
import 'package:aman_kassa_flutter/redux/state/user_state.dart'; import 'package:aman_kassa_flutter/core/locator.dart';
import 'package:aman_kassa_flutter/core/models/message.dart';
import 'package:aman_kassa_flutter/core/models/response.dart';
import 'package:aman_kassa_flutter/core/models/dialog_models.dart';
import 'package:aman_kassa_flutter/core/models/smena.dart';
import 'package:aman_kassa_flutter/core/route_names.dart';
import 'package:aman_kassa_flutter/core/services/ApiService.dart';
import 'package:aman_kassa_flutter/core/services/dialog_service.dart';
import 'package:aman_kassa_flutter/core/services/navigator_service.dart';
import 'package:aman_kassa_flutter/redux/actions/user_actions.dart';
import 'package:aman_kassa_flutter/redux/actions/setting_actions.dart';
import 'package:aman_kassa_flutter/redux/constants/setting_const.dart';
import 'package:aman_kassa_flutter/redux/state/setting_state.dart';
import 'package:aman_kassa_flutter/redux/store.dart'; import 'package:aman_kassa_flutter/redux/store.dart';
import 'package:aman_kassa_flutter/shared/app_colors.dart'; import 'package:aman_kassa_flutter/shared/app_colors.dart';
import 'package:aman_kassa_flutter/shared/ui_helpers.dart'; import 'package:aman_kassa_flutter/shared/ui_helpers.dart';
import 'package:aman_kassa_flutter/views/check/image_show_container.dart';
import 'package:aman_kassa_flutter/widgets/fields/aman_icon_button.dart';
import 'package:aman_kassa_flutter/widgets/fields/aman_icon_button_horizontal.dart';
import 'package:aman_kassa_flutter/widgets/fields/busy_button.dart'; import 'package:aman_kassa_flutter/widgets/fields/busy_button.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:google_fonts/google_fonts.dart'; import 'package:material_design_icons_flutter/material_design_icons_flutter.dart';
class AdditionalTab extends StatelessWidget { class AdditionalTab extends StatefulWidget {
final int index; final int index;
AdditionalTab(this.index); AdditionalTab(this.index);
@override
_AdditionalTabState createState() => _AdditionalTabState();
}
class _AdditionalTabState extends State<AdditionalTab> {
ApiService _api = locator<ApiService>();
NavigatorService _navigator = locator<NavigatorService>();
DialogService _dialog = locator<DialogService>();
bool isMoneyCheckBusy;
bool closeSmenaBusy;
bool openSmenaBusy;
bool depositBusy;
bool withdrawalBusy;
bool xReportBusy;
@override
void initState() {
super.initState();
isMoneyCheckBusy = false;
closeSmenaBusy = false;
openSmenaBusy = false;
depositBusy = false;
withdrawalBusy = false;
xReportBusy = false;
}
void _closeSmena() async {
setState(() {
closeSmenaBusy = true;
});
await Redux.store.dispatch(closeSmena);
setState(() {
closeSmenaBusy = false;
});
}
void _openSmena() async {
setState(() {
openSmenaBusy = true;
});
await Redux.store.dispatch(openSmena);
setState(() {
openSmenaBusy = false;
});
}
void _xReport() async {
setState(() {
xReportBusy = true;
});
Response response =
await _api.xReport(Redux.store.state.userState.user.token);
if (response.operation) {
_navigator.push(ImageShowRoute,
arguments: ImageShowModel(response.body['check'], 'X Отчет'));
} else {
_dialog.showDialog(description: response.body['message']);
}
setState(() {
xReportBusy = false;
});
}
void _deposit() async {
setState(() {
depositBusy = true;
});
try {
DialogResponse response = await _dialog.showConfirmationDialogInput(
description: 'Укажите сумму',
cancelTitle: 'Отмена',
confirmationTitle: 'Взнос',
);
if (response.confirmed) {
Response<dynamic> result = await _api.deposit(
Redux.store.state.userState.user.token, response.responseText);
//if(result.operation) {
_dialog.showDialog(description: result.body['message']);
//}
}
} catch (e) {
print(e);
} finally {
setState(() {
depositBusy = false;
});
}
}
void _withdrawal() async {
setState(() {
withdrawalBusy = true;
});
try {
DialogResponse response = await _dialog.showConfirmationDialogInput(
description: 'Укажите сумму',
cancelTitle: 'Отмена',
confirmationTitle: 'Снятие',
);
if (response.confirmed) {
Response<dynamic> result = await _api.withdrawal(
Redux.store.state.userState.user.token, response.responseText);
//if(result.operation) {
_dialog.showDialog(description: result.body['message']);
//}
}
} catch (e) {
print(e);
} finally {
setState(() {
withdrawalBusy = false;
});
}
}
void _checkMoney() async {
setState(() {
isMoneyCheckBusy = true;
});
try {
Response<dynamic> result =
await _api.money(Redux.store.state.userState.user.token);
setState(() {
isMoneyCheckBusy = false;
});
if (result.operation) {
_dialog.showDialog(
description: 'Денег в кассе: ${result.body['money']}');
} else {
_dialog.showDialog(description: '${result.body['message']}');
}
} catch (e) {
print(e);
setState(() {
isMoneyCheckBusy = false;
});
}
}
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return StoreConnector<AppState, UserState>(
converter: (store) => store.state.userState,
builder: (context, vm) {
return Container( return Container(
padding: const EdgeInsets.symmetric(vertical: 15), padding: const EdgeInsets.symmetric(vertical: 15),
child: ListView(
children: <Widget>[
Padding(
padding: const EdgeInsets.symmetric(horizontal: 20.0),
child: StoreConnector<AppState, SettingState>(
converter: (store) => store.state.settingState,
builder: (context, vm) {
return Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Expanded(
flex: 1,
child: AmanIconButtonHorizontal(
icon: MdiIcons.calculator,
title: 'Калькулятор',
selected: vm.mode == SettingModeCalc,
onPressed: () => changeMode(false),
)),
Expanded(
flex: 1,
child: Center(
child: Switch(
value: vm.mode == SettingModeKassa,
onChanged: changeMode,
inactiveThumbColor: primaryColor,
activeColor: primaryColor,
))),
Expanded(
flex: 1,
child: AmanIconButtonHorizontal(
icon: MdiIcons.cashRegister,
title: 'Режим кассы',
selected: vm.mode == SettingModeKassa,
onPressed: () => changeMode(true))),
],
);
}),
),
Divider(),
verticalSpaceMedium,
Padding(
padding: const EdgeInsets.symmetric(horizontal: 20.0),
child: Center(
child: Column( child: Column(
children: <Widget>[ children: <Widget>[
verticalSpaceLarge, Text(
'Денег в кассе:',
style: TextStyle(color: primaryColor, fontSize: 15),
),
Text(
'250 024.38 тенге',
style: TextStyle(
color: primaryColor,
fontSize: 25,
fontWeight: FontWeight.bold),
),
],
)),
),
verticalSpaceMedium,
Row( Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly, mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[ children: <Widget>[
BusyButton(title: 'Открыть смену', onPressed: null, mainColor: greenColor,), AmanIconButton(
BusyButton(title: 'Закрыть смену', onPressed: null, mainColor: redColor ,), title: 'Открыть смену',
onPressed: _openSmena,
mainColor: greenColor,
busy: openSmenaBusy,
icon: Icons.lock_open,
),
AmanIconButton(
title: 'Закрыть смену',
onPressed: _closeSmena,
mainColor: redColor,
busy: closeSmenaBusy,
icon: Icons.lock_outline,
),
AmanIconButton(
title: 'Денег в кассе',
onPressed: _checkMoney,
busy: isMoneyCheckBusy,
icon: Icons.attach_money,
mainColor: primaryColor,
),
], ],
), ),
verticalSpaceLarge, verticalSpaceTiny,
Row( Row(
mainAxisAlignment: MainAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[ children: <Widget>[
BusyButton(title: 'Денег в кассе', onPressed: null,), AmanIconButton(
title: 'Х Отчет',
onPressed: _xReport,
busy: xReportBusy,
mainColor: primaryColor,
icon: Icons.description,
),
], ],
), ),
verticalSpaceLarge, verticalSpaceMedium,
Row( Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly, mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[ children: <Widget>[
BusyButton(title: 'Взнос наличных', onPressed: null,), BusyButton(
BusyButton(title: 'Снятие наличных', onPressed: null, mainColor: redColor ,), title: 'Взнос наличных',
onPressed: _deposit,
busy: depositBusy,
),
BusyButton(
title: 'Снятие наличных',
onPressed: _withdrawal,
mainColor: redColor,
busy: withdrawalBusy,
),
], ],
), ),
verticalSpaceLarge,
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
BusyButton(title: 'Х Отчет', onPressed: null,),
],
)
], ],
), ),
); );
}, }
); void changeMode(el) {
Redux.store.dispatch(changeModeFromSetting(el));
} }
} }

View File

@ -1,10 +1,26 @@
import 'package:aman_kassa_flutter/core/locator.dart';
import 'package:aman_kassa_flutter/core/route_names.dart';
import 'package:aman_kassa_flutter/core/services/navigator_service.dart';
import 'package:aman_kassa_flutter/redux/actions/calc_actions.dart';
import 'package:aman_kassa_flutter/redux/constants/operation_const.dart';
import 'package:aman_kassa_flutter/redux/constants/setting_const.dart';
import 'package:aman_kassa_flutter/redux/state/calc_state.dart';
import 'package:aman_kassa_flutter/redux/store.dart';
import 'package:aman_kassa_flutter/shared/app_colors.dart';
import 'package:aman_kassa_flutter/shared/shared_styles.dart';
import 'package:aman_kassa_flutter/views/payment/payment_view.dart';
import 'package:aman_kassa_flutter/widgets/components/calculator/calculator.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:aman_kassa_flutter/widgets/components/calculator/calculator-buttons.dart'; import 'package:aman_kassa_flutter/widgets/components/calculator/calculator-buttons.dart';
import 'package:aman_kassa_flutter/widgets/components/calculator/number-display.dart'; import 'package:aman_kassa_flutter/widgets/components/calculator/number-display.dart';
import 'package:flutter_redux/flutter_redux.dart';
class CalculatorTab extends StatelessWidget { class CalculatorTab extends StatelessWidget {
NavigatorService _navigatorService = locator<NavigatorService>();
final int index; final int index;
CalculatorTab(this.index); CalculatorTab(this.index);
@ -14,10 +30,53 @@ class CalculatorTab extends StatelessWidget {
return Scaffold( return Scaffold(
body: Column( body: Column(
children: <Widget>[ children: <Widget>[
NumberDisplay(value: 'values'), StoreConnector<AppState, CalcState>(
CalculatorButtons(onTap: null), converter: (store) => store.state.calcState,
builder: (context, vm) {
return NumberDisplay(value: Calculator.parseItems(vm.calcItems, vm.isEqual));
}
),
CalculatorButtons(onTap: _onPress),
Row(
children: <Widget>[
Expanded(
child: RaisedButton(
padding: EdgeInsets.all(10.0),
color: redColor,
child: Text(
"Возврат",
style: buttonBigTitleTextStyle,
),
onPressed: () {
_navigatorService.push(PaymentViewRoute, arguments: PaymentModel(mode: SettingModeCalc, operationType: OperationTypeReturn) );
}
),
),
Expanded(
child: RaisedButton(
padding: EdgeInsets.all(10.0),
color: greenColor,
child: Text(
"Оплата",
style: buttonBigTitleTextStyle,
),
onPressed: () {
_navigatorService.push(PaymentViewRoute, arguments: PaymentModel(mode: SettingModeCalc, operationType: OperationTypePay) );
},
),
),
],
)
], ],
mainAxisAlignment: MainAxisAlignment.spaceBetween, mainAxisAlignment: MainAxisAlignment.spaceBetween,
)); ));
} }
void _onPress({ String buttonText}) {
Redux.store.dispatch(onTapAction(buttonText));
}
} }

View File

@ -1,25 +1,33 @@
import 'package:aman_kassa_flutter/core/models/ProductDao.dart'; import 'package:aman_kassa_flutter/core/locator.dart';
import 'package:aman_kassa_flutter/redux/actions/main_actions.dart'; import 'package:aman_kassa_flutter/core/models/product_dao.dart';
import 'package:aman_kassa_flutter/redux/state/main_state.dart'; import 'package:aman_kassa_flutter/core/route_names.dart';
import 'package:aman_kassa_flutter/core/services/navigator_service.dart';
import 'package:aman_kassa_flutter/redux/actions/kassa_actions.dart';
import 'package:aman_kassa_flutter/redux/constants/operation_const.dart';
import 'package:aman_kassa_flutter/redux/constants/setting_const.dart';
import 'package:aman_kassa_flutter/redux/state/kassa_state.dart';
import 'package:aman_kassa_flutter/redux/store.dart'; import 'package:aman_kassa_flutter/redux/store.dart';
import 'package:aman_kassa_flutter/shared/app_colors.dart'; import 'package:aman_kassa_flutter/shared/app_colors.dart';
import 'package:aman_kassa_flutter/shared/shared_styles.dart'; import 'package:aman_kassa_flutter/shared/shared_styles.dart';
import 'package:aman_kassa_flutter/views/home/tabs/kassaView/CatalogBottomSheet.dart'; import 'package:aman_kassa_flutter/views/home/tabs/kassaView/CatalogBottomSheet.dart';
import 'package:aman_kassa_flutter/views/home/tabs/kassaView/ProductAddBottomSheet.dart'; import 'package:aman_kassa_flutter/views/home/tabs/kassaView/ProductAddBottomSheet.dart';
import 'package:aman_kassa_flutter/views/payment/payment_view.dart';
import 'package:aman_kassa_flutter/widgets/components/ProductListItem.dart'; import 'package:aman_kassa_flutter/widgets/components/ProductListItem.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';
class KassaTab extends StatelessWidget { class KassaTab extends StatelessWidget {
NavigatorService _navigatorService = locator<NavigatorService>();
final int index; final int index;
KassaTab(this.index); KassaTab(this.index);
Widget buildItem(BuildContext ctxt, int index, ProductDao productDao) { Widget buildItem(BuildContext ctxt, int index, ProductDao productDao) {
return ProductListItem( return ProductListItem(
item: new ProductDao(name: productDao.name, count: productDao.count, price: productDao.price), item: productDao,
index: index, index: index,
); );
} }
@ -64,8 +72,8 @@ class KassaTab extends StatelessWidget {
), ),
Expanded( Expanded(
child: Container( child: Container(
child: StoreConnector<AppState, MainState>( child: StoreConnector<AppState, KassaState>(
converter: (store) => store.state.mainState, converter: (store) => store.state.kassaState,
builder: (context, vm) { builder: (context, vm) {
return ListView.builder( return ListView.builder(
itemCount: vm.kassaItems.length, itemCount: vm.kassaItems.length,
@ -75,6 +83,21 @@ class KassaTab extends StatelessWidget {
), ),
), ),
), ),
Divider(),
Container(
margin: const EdgeInsets.symmetric(vertical: 8),
child: Row(
mainAxisAlignment: MainAxisAlignment.end,
children: <Widget>[
StoreConnector<AppState, KassaState>(
converter: (store) => store.state.kassaState,
builder: (context, vm) {
return Text(totalCalc(vm.kassaItems), style: TextStyle(fontSize: 25));
}
),
],
),
),
Row( Row(
children: <Widget>[ children: <Widget>[
Expanded( Expanded(
@ -87,7 +110,9 @@ class KassaTab extends StatelessWidget {
"Возврат", "Возврат",
style: buttonBigTitleTextStyle, style: buttonBigTitleTextStyle,
), ),
onPressed: () => null, onPressed: () {
_navigatorService.push(PaymentViewRoute, arguments: PaymentModel(mode: SettingModeKassa, operationType: OperationTypeReturn) );
}
), ),
), ),
), ),
@ -101,7 +126,9 @@ class KassaTab extends StatelessWidget {
"Оплата", "Оплата",
style: buttonBigTitleTextStyle, style: buttonBigTitleTextStyle,
), ),
onPressed: () => null, onPressed: () {
_navigatorService.push(PaymentViewRoute, arguments: PaymentModel(mode: SettingModeKassa, operationType: OperationTypePay) );
},
), ),
), ),
), ),
@ -112,6 +139,14 @@ class KassaTab extends StatelessWidget {
); );
} }
String totalCalc(List<ProductDao> kassaItems) {
num total = 0.0;
kassaItems.forEach((element) {
total+= element.total == null ? 0.0 : element.total.toDouble();
});
return total.toString();
}
void showModalBottomSheetCatalog(BuildContext context, String action) { void showModalBottomSheetCatalog(BuildContext context, String action) {
showModalBottomSheet( showModalBottomSheet(
context: context, context: context,

View File

@ -1,7 +1,14 @@
import 'package:aman_kassa_flutter/core/entity/Category.dart'; import 'package:aman_kassa_flutter/core/entity/Category.dart';
import 'package:aman_kassa_flutter/core/entity/Goods.dart'; import 'package:aman_kassa_flutter/core/entity/Goods.dart';
import 'package:aman_kassa_flutter/redux/actions/main_actions.dart'; import 'package:aman_kassa_flutter/core/entity/Service.dart';
import 'package:aman_kassa_flutter/redux/state/main_state.dart'; import 'package:aman_kassa_flutter/core/locator.dart';
import 'package:aman_kassa_flutter/core/models/Choice.dart';
import 'package:aman_kassa_flutter/core/services/dialog_service.dart';
import 'package:aman_kassa_flutter/redux/actions/kassa_actions.dart';
import 'package:aman_kassa_flutter/redux/actions/setting_actions.dart';
import 'package:aman_kassa_flutter/redux/constants/setting_const.dart';
import 'package:aman_kassa_flutter/redux/state/kassa_state.dart';
import 'package:aman_kassa_flutter/redux/state/setting_state.dart';
import 'package:aman_kassa_flutter/redux/store.dart'; import 'package:aman_kassa_flutter/redux/store.dart';
import 'package:aman_kassa_flutter/shared/app_colors.dart'; import 'package:aman_kassa_flutter/shared/app_colors.dart';
import 'package:aman_kassa_flutter/shared/shared_styles.dart'; import 'package:aman_kassa_flutter/shared/shared_styles.dart';
@ -15,8 +22,8 @@ class CatalogBottomSheet extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return StoreConnector<AppState, MainState>( return StoreConnector<AppState, KassaState>(
converter: (store) => store.state.mainState, converter: (store) => store.state.kassaState,
onInit: (store) => Redux.store.dispatch(selectBottomElement(0)), onInit: (store) => Redux.store.dispatch(selectBottomElement(0)),
builder: (context, vm) { builder: (context, vm) {
return WillPopScope( return WillPopScope(
@ -36,8 +43,8 @@ class CatalogBottomSheet extends StatelessWidget {
style: TextStyle(color: Colors.black45), style: TextStyle(color: Colors.black45),
), ),
iconTheme: IconThemeData(color: Colors.black), iconTheme: IconThemeData(color: Colors.black),
backgroundColor: fillColor, backgroundColor: whiteColor,
elevation: 3, elevation: 1,
leading: IconButton( leading: IconButton(
icon: Icon(vm.prevCategories.length > 0 icon: Icon(vm.prevCategories.length > 0
? Icons.arrow_back ? Icons.arrow_back
@ -49,6 +56,7 @@ class CatalogBottomSheet extends StatelessWidget {
Navigator.pop(context); Navigator.pop(context);
}, },
), ),
actions: <Widget>[buildActionContainer()],
), ),
body: Column( body: Column(
crossAxisAlignment: CrossAxisAlignment.stretch, crossAxisAlignment: CrossAxisAlignment.stretch,
@ -60,30 +68,49 @@ class CatalogBottomSheet extends StatelessWidget {
itemBuilder: (context, index) { itemBuilder: (context, index) {
var el = vm.bottomSheetElements[index]; var el = vm.bottomSheetElements[index];
String name; String name;
String price;
if (el is Category) { if (el is Category) {
Category category = el; Category category = el;
name = category.name; name = category.name;
} else if (el is Good) { } else if (el is Good) {
Good good = el; Good good = el;
name = good.name; name = good.name;
price = good.price.toString();
} else if (el is Service) {
Service service = el;
name = service.name;
price = service.price.toString();
} }
return Card( return Card(
child: ListTile( child: ListTile(
leading: Icon( leading: el is Category
el is Category ? Icons.layers : Icons.move_to_inbox, ? Icon(Icons.layers, size: 25)
size: 40, : null,
title: Text(
name,
style: TextStyle(fontSize: 15),
), ),
title: Text(name),
onTap: () async { onTap: () async {
if (el is Category) { if (el is Category) {
Redux.store.dispatch(selectBottomElement(el.id)); Redux.store
.dispatch(selectBottomElement(el.id));
} else if (el is Good) { } else if (el is Good) {
await Redux.store.dispatch(addProductToKassaItems(el)); await Redux.store
.dispatch(addProductToKassaItems(el));
Navigator.pop(context);
} else if (el is Service) {
await Redux.store
.dispatch(addServiceToKassaItems(el));
Navigator.pop(context); Navigator.pop(context);
} }
}, },
trailing: trailing: el is Category
el is Category ? Icon(Icons.chevron_right) : null, ? Icon(Icons.chevron_right)
: Text(
price,
style: TextStyle(
fontSize: 15, color: Colors.black54),
),
), ),
); );
}, },
@ -104,4 +131,68 @@ class CatalogBottomSheet extends StatelessWidget {
}, },
); );
} }
Container buildActionContainer() {
return Container(
margin: const EdgeInsets.symmetric(horizontal: 15.0, vertical: 5.0),
child: StoreConnector<AppState, KassaState>(
converter: (store) => store.state.kassaState,
builder: (_, mainState) {
return StoreConnector<AppState, SettingState>(
converter: (store) => store.state.settingState,
builder: (_, settingState) {
if (mainState.kassaItems.isNotEmpty) {
return GestureDetector(
onTap: () {
locator<DialogService>().showDialog(
description:
'Выбрать другой тип продажи, возможно только при пустом списке покупок');
},
child: Container(
child: Text(
settingState.tradeType == SettingTradeTypeGood
? 'Товары'
: 'Услуги',
style: dropDownTradeTypeTextStyle,
),
padding: const EdgeInsets.symmetric(vertical: 8.0),
));
}
return DropdownButton<String>(
value: settingState.tradeType,
icon: Icon(
Icons.arrow_drop_down_circle,
color: yellowColor,
),
iconSize: 24,
elevation: 6,
style: dropDownTradeTypeTextStyle,
underline: Container(
height: 1,
),
onChanged: (String newValue) {
onChangeTradeType(newValue, settingState.tradeType);
},
items: [
DropdownMenuItem<String>(
child: Text('Товары'),
value: SettingTradeTypeGood,
),
DropdownMenuItem<String>(
child: Text('Услуги'),
value: SettingTradeTypeService,
)
],
);
});
}),
);
}
void onChangeTradeType(String newValue, String oldValue) async {
if (oldValue != newValue) {
await Redux.store.dispatch(changeTradeTypeFromSetting(newValue));
await Redux.store.dispatch(selectBottomElement(0));
}
}
} }

View File

@ -1,4 +1,4 @@
import 'package:aman_kassa_flutter/redux/actions/main_actions.dart'; import 'package:aman_kassa_flutter/redux/actions/kassa_actions.dart';
import 'package:aman_kassa_flutter/redux/store.dart'; import 'package:aman_kassa_flutter/redux/store.dart';
import 'package:aman_kassa_flutter/shared/app_colors.dart'; import 'package:aman_kassa_flutter/shared/app_colors.dart';
import 'package:aman_kassa_flutter/shared/ui_helpers.dart'; import 'package:aman_kassa_flutter/shared/ui_helpers.dart';
@ -155,7 +155,7 @@ class _ProductAddBottomSheetState extends State<ProductAddBottomSheet> {
_showDialog(); _showDialog();
} else { } else {
Redux.store.dispatch(addCustomProductToKassaItems(nameController.text, Redux.store.dispatch(addCustomProductToKassaItems(nameController.text,
int.parse(countController.text), double.parse(priceController.text))); int.parse(countController.text), double.parse(priceController.text), sum));
Navigator.pop(context); Navigator.pop(context);
} }
} }

View File

@ -25,7 +25,6 @@ class LoginView extends StatelessWidget {
return StoreConnector<AppState, UserState>( return StoreConnector<AppState, UserState>(
converter: (store) => store.state.userState, converter: (store) => store.state.userState,
builder: (context, vm) { builder: (context, vm) {
print('build');
return Scaffold( return Scaffold(
key: _scaffoldKey, key: _scaffoldKey,
backgroundColor: fillColor, backgroundColor: fillColor,

View File

@ -0,0 +1,179 @@
import 'package:aman_kassa_flutter/core/locator.dart';
import 'package:aman_kassa_flutter/core/models/calc_model.dart';
import 'package:aman_kassa_flutter/core/models/product_dao.dart';
import 'package:aman_kassa_flutter/core/models/response.dart';
import 'package:aman_kassa_flutter/core/route_names.dart';
import 'package:aman_kassa_flutter/core/services/DataService.dart';
import 'package:aman_kassa_flutter/core/services/dialog_service.dart';
import 'package:aman_kassa_flutter/core/services/navigator_service.dart';
import 'package:aman_kassa_flutter/redux/constants/operation_const.dart';
import 'package:aman_kassa_flutter/redux/constants/setting_const.dart';
import 'package:aman_kassa_flutter/redux/state/calc_state.dart';
import 'package:aman_kassa_flutter/redux/state/kassa_state.dart';
import 'package:aman_kassa_flutter/redux/store.dart';
import 'package:aman_kassa_flutter/shared/app_colors.dart';
import 'package:aman_kassa_flutter/shared/ui_helpers.dart';
import 'package:aman_kassa_flutter/views/check/image_show_container.dart';
import 'package:aman_kassa_flutter/widgets/components/calculator/calculator.dart';
import 'package:aman_kassa_flutter/widgets/fields/busy_button.dart';
import 'package:aman_kassa_flutter/widgets/loader/Dialogs.dart';
import 'package:flutter/material.dart';
import 'package:flutter_redux/flutter_redux.dart';
class PaymentView extends StatefulWidget {
final PaymentModel model;
const PaymentView({Key key, this.model}) : super(key: key);
@override
_PaymentViewState createState() => _PaymentViewState();
}
class _PaymentViewState extends State<PaymentView> {
final GlobalKey<State> _keyLoader = new GlobalKey<State>();
final DataService _dataService = locator<DataService>();
final DialogService _dialogService = locator<DialogService>();
final NavigatorService _navigatorService = locator<NavigatorService>();
bool isBusy;
@override
void initState() {
// TODO: implement initState
super.initState();
isBusy = false;
}
@override
Widget build(BuildContext context) {
return WillPopScope(
onWillPop: () {
if (!isBusy)
Navigator.pop(context);
return new Future(() => false);
},
child: Scaffold(
appBar: AppBar(
backgroundColor: whiteColor,
elevation: 0,
leading: IconButton(icon: Icon(Icons.arrow_back_ios), color: Colors.black87, onPressed: () => Navigator.pop(context),),
title: Text(dataTitle(), style: TextStyle(color: Colors.black87),),
),
body: Container(
padding: const EdgeInsets.symmetric(vertical: 12.0, horizontal: 12.0 ),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text(dataText() , style: TextStyle(fontWeight: FontWeight.bold, color: Colors.black26, fontSize: 15 ),),
buildStoreConnector(),
verticalSpaceLarge,
_buildBodyContent(),
],
),
),
),
);
}
String dataTitle() => widget.model.operationType == OperationTypePay ? 'Оплата' : 'Возврат';
String dataText() => widget.model.operationType == OperationTypePay ? 'К оплате' : 'К возврату';
StoreConnector buildStoreConnector() {
if(widget.model.mode == SettingModeCalc) {
return StoreConnector<AppState, CalcState>(
converter: (store) => store.state.calcState,
builder: (context, vm) {
return Text('${totalCalc(vm.calcItems)} тнг', style: TextStyle(
fontWeight: FontWeight.bold,
color: Colors.black87,
fontSize: 35));
}
);
}
return StoreConnector<AppState, KassaState>(
converter: (store) => store.state.kassaState,
builder: (context, vm) {
return Text('${totalKassa(vm.kassaItems)} тнг', style: TextStyle(fontWeight: FontWeight.bold, color: Colors.black87, fontSize: 35 ));
}
);
}
Expanded _buildBodyContent() {
return Expanded(
child: Column(
children: <Widget>[
Container(
height: 150,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
Expanded(child: BusyButton(title: 'Оплатить картой', onPressed:() { pressPayment('card');}, mainColor: greenColor,)),
horizontalSpaceSmall,
Expanded(child: BusyButton(title: 'Наличными', onPressed:() { pressPayment('cash');}, mainColor: primaryColor,)),
],
),
),
verticalSpaceLarge,
Expanded(child: Container(),),
Container(child: BusyButton(title: 'Отмена', onPressed:() { Navigator.pop(context);} , mainColor: redColor,)),
],
),
);
}
pressPayment(String type) async {
setState(() { isBusy = true; });
Dialogs.showLoadingDialog(context, _keyLoader);
try {
AppState _state = Redux.store.state;
String _token = _state.userState.user.token;
String _tradeType = _state.settingState.tradeType;
List<ProductDao> items = _state.kassaState.kassaItems;
Response<dynamic> response = await _dataService.sellOrReturn(token: _token, items: items, paymentType: type, operationType: widget.model.operationType, tradeType: _tradeType );
Navigator.of(context, rootNavigator: true).pop();
setState(() { isBusy = false; });
if(response.operation){
String message = response.body['message'];
String check = response.body['check'];
_navigatorService.pop();
_navigatorService.push(ImageShowRoute, arguments: ImageShowModel(check, message));
} else if(!response.operation && response.status !=500) {
_dialogService.showDialog(description: response.body['message']);
}
} catch(e) {
//Navigator.of(_keyLoader.currentContext, rootNavigator: true).pop();
Navigator.of(context, rootNavigator: true).pop();
setState(() { isBusy = false; });
}
}
String totalKassa(List<ProductDao> kassaItems) {
num total = 0.0;
kassaItems.forEach((element) {
total+= element.total == null ? 0.0 : element.total.toDouble();
});
return total.toString();
}
String totalCalc(List<CalcModel> items) {
num total = 0.0;
items.forEach((element) {
if(element.operation == Calculations.MULTIPLY) {
double num1 = element.num1 == null ? 0.0 : double.parse(element.num1);
double num2 = element.num2 == null ? 0.0 : double.parse(element.num2);
total += num1 * num2;
} else {
total+= element.num1 == null ? 0.0 : double.parse(element.num1);
}
});
return total.toString();
}
}
class PaymentModel {
String operationType;
String mode;
PaymentModel({this.mode, this.operationType});
}

View File

@ -34,8 +34,6 @@ class _StartUpViewState extends State<StartUpView> {
height: 200, height: 200,
child: Image.asset('assets/images/icon_large.png'), child: Image.asset('assets/images/icon_large.png'),
), ),
Text('${userState.isLoading}'),
Text('${userState.isAuthenticated}'),
CircularProgressIndicator( CircularProgressIndicator(
strokeWidth: 3, strokeWidth: 3,
valueColor: AlwaysStoppedAnimation( valueColor: AlwaysStoppedAnimation(

View File

@ -1,9 +1,9 @@
import 'package:aman_kassa_flutter/redux/actions/main_actions.dart'; import 'package:aman_kassa_flutter/redux/actions/kassa_actions.dart';
import 'package:aman_kassa_flutter/redux/store.dart'; import 'package:aman_kassa_flutter/redux/store.dart';
import 'package:aman_kassa_flutter/shared/shared_styles.dart'; import 'package:aman_kassa_flutter/shared/shared_styles.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:aman_kassa_flutter/shared/app_colors.dart'; import 'package:aman_kassa_flutter/shared/app_colors.dart';
import 'package:aman_kassa_flutter/core/models/ProductDao.dart'; import 'package:aman_kassa_flutter/core/models/product_dao.dart';
class ProductListItem extends StatelessWidget { class ProductListItem extends StatelessWidget {
final ProductDao item; final ProductDao item;
@ -28,7 +28,7 @@ class ProductListItem extends StatelessWidget {
child: Container( child: Container(
padding: const EdgeInsets.symmetric(vertical: 8, horizontal: 4), padding: const EdgeInsets.symmetric(vertical: 8, horizontal: 4),
child: Text( child: Text(
'${item.price?.toString()} x ${item.count?.toString()}', '${item.price?.toString()} x ${item.count?.toString()} = ${item.total?.toString()}',
textAlign: TextAlign.right, style: productTextStyle)), textAlign: TextAlign.right, style: productTextStyle)),
) )
], ],

View File

@ -20,7 +20,7 @@ class CalculatorButton extends StatelessWidget {
decoration: BoxDecoration( decoration: BoxDecoration(
border: Border.all( border: Border.all(
color: Colors.black, color: Colors.black,
width: 1, width: 1.2,
), ),
), ),
child: FlatButton( child: FlatButton(

View File

@ -1,3 +1,5 @@
import 'package:aman_kassa_flutter/core/models/calc_model.dart';
import 'number-formatter.dart'; import 'number-formatter.dart';
class Calculations { class Calculations {
@ -5,7 +7,8 @@ class Calculations {
static const MULTIPLY = '*'; static const MULTIPLY = '*';
static const SUBTRACT = '-'; static const SUBTRACT = '-';
static const ADD = '+'; static const ADD = '+';
static const DIVIDE = '/'; static const NONE = 'none';
static const ERASE = '<<'; static const ERASE = '<<';
static const CLEAR = 'C'; static const CLEAR = 'C';
static const EQUAL = '='; static const EQUAL = '=';
@ -13,72 +16,273 @@ class Calculations {
Calculations.ADD, Calculations.ADD,
Calculations.MULTIPLY, Calculations.MULTIPLY,
Calculations.SUBTRACT, Calculations.SUBTRACT,
Calculations.DIVIDE,
Calculations.ERASE Calculations.ERASE
]; ];
static double add(double a, double b) => a + b; static double add(double a, double b) => a + b;
static double subtract(double a, double b) => a - b; static double subtract(double a, double b) => a - b;
static double divide(double a, double b) => a / b; static double divide(double a, double b) => a / b;
static double multiply(double a, double b) => a * b; static double multiply(double a, double b) => a * b;
} }
class Calculator { class Calculator {
static String parseString(String text) { static String parseItems(List<CalcModel> items, bool isEqual) {
List<String> numbersToAdd; if (isEqual) {
double a, b, result; return _viewResult(items);
if (text.contains(Calculations.ADD)) {
numbersToAdd = text.split(Calculations.ADD);
a = double.parse(numbersToAdd[0]);
b = double.parse(numbersToAdd[1]);
result = Calculations.add(a, b);
} else if (text.contains(Calculations.MULTIPLY)) {
numbersToAdd = text.split(Calculations.MULTIPLY);
a = double.parse(numbersToAdd[0]);
b = double.parse(numbersToAdd[1]);
result = Calculations.multiply(a, b);
} else if (text.contains(Calculations.DIVIDE)) {
numbersToAdd = text.split(Calculations.DIVIDE);
a = double.parse(numbersToAdd[0]);
b = double.parse(numbersToAdd[1]);
result = Calculations.divide(a, b);
} else if (text.contains(Calculations.SUBTRACT)) {
numbersToAdd = text.split(Calculations.SUBTRACT);
a = double.parse(numbersToAdd[0]);
b = double.parse(numbersToAdd[1]);
result = Calculations.subtract(a, b);
} else { } else {
return text; return _viewValues(items);
}
return NumberFormatter.format(result.toString());
}
static String addPeriod(String calculatorString) {
if (calculatorString.isEmpty) {
return calculatorString = '0${Calculations.PERIOD}';
}
RegExp exp = new RegExp(r"\d\.");
Iterable<Match> matches = exp.allMatches(calculatorString);
int maxMatches = Calculator.includesOperation(calculatorString) ? 2 : 1;
return matches.length == maxMatches
? calculatorString
: calculatorString += Calculations.PERIOD;
}
static bool includesOperation(String calculatorString) {
for (var operation in Calculations.OPERATIONS) {
if (calculatorString.contains(operation)) {
return true;
} }
} }
return false; static String _viewResult(List<CalcModel> items) {
String str = '';
if (items.isNotEmpty) {
CalcModel last = items.removeLast();
if (last.operation == Calculations.NONE && last.num1 != '0') {
last.operation = Calculations.ADD;
} else if (last.operation == Calculations.MULTIPLY) {
if (last.num2 == null) {
last.num2 = '1';
last.operation = Calculations.ADD;
}
}
last.closed = true;
items.add(last);
double summ = 0.0;
for (var i = 0; i < items.length; i++) {
var row = items[i];
if (row.operation == Calculations.MULTIPLY) {
str += "${row.num1} * ${row.num2}" ;
summ += double.parse(row.num1) * double.parse(row.num2);
} else {
str += row.num1;
summ += double.parse(row.num1) ;
}
if (row.closed) {
if (i < items.length - 1) {
str += " + ";
} else {
str += " = ";
}
}
}
str += summ.toStringAsFixed(2);
}
return str;
}
static String _viewValues(List<CalcModel> items) {
String str = '';
for (var i = 0; i < items.length; i++) {
CalcModel row = items[i];
if (row.operation == Calculations.ADD) {
str += row.num1;
} else if (row.operation == Calculations.MULTIPLY) {
if (row.num2 == null) {
str += row.num1 + " * ";
} else {
str += row.num1 + " * " + row.num2;
}
} else if (row.operation == Calculations.NONE) {
str += row.num1;
} else if (row.operation == Calculations.EQUAL) {
str += row.num1;
}
if (row.closed) {
str += " + ";
}
}
return str;
}
static List<CalcModel> action({String value, List<CalcModel> items}) {
switch (value) {
case Calculations.ADD:
{
items = _setPlus(value: value, items: items);
}
break;
case Calculations.MULTIPLY:
{
items = _setMultiply(value: value, items: items);
}
break;
case Calculations.ERASE:
{
items = _setBackward(value: value, items: items);
}
break;
case Calculations.CLEAR:
{
items = _setClean(value: value, items: items);
}
break;
case Calculations.PERIOD:
{
items = _setDot(value: value, items: items);
}
break;
case Calculations.EQUAL:
{
items = _setEqual(value: value, items: items);
}
break;
default:
{
items = _setNumber(value: value, items: items);
}
break;
}
return [...items];
}
static List<CalcModel> _setNumber({String value, List<CalcModel> items}) {
if (items.isEmpty) {
items.add(CalcModel(num1: value, operation: Calculations.NONE));
} else {
CalcModel last = items.removeLast();
if (last.closed) {
items.add(last);
items.add(CalcModel(num1: value, operation: Calculations.NONE));
} else {
if (value == '0' && last.num1 == '0') {
last.operation = Calculations.NONE;
items.add(last);
} else if (value == '0' && last.num1 == '0.') {
last.num1 += value;
last.operation = Calculations.NONE;
items.add(last);
} else {
if (last.operation == Calculations.NONE) {
if (last.num1 == '0' && value != '0') {
last.num1 = value;
} else {
last.num1 += value;
}
items.add(last);
} else if (last.operation == Calculations.MULTIPLY) {
if(last.num2 == null)
last.num2 = value;
else
last.num2 += value;
last.operation = Calculations.MULTIPLY;
items.add(last);
} else if (last.operation == Calculations.ADD) {
last.operation = Calculations.ADD;
items.add(last);
}
}
}
}
return [...items];
}
static List<CalcModel> _setPlus({String value, List<CalcModel> items}) {
if (items.isNotEmpty) {
CalcModel last = items.removeLast();
if (last.closed) {
items.add(last);
} else {
if (last.operation == Calculations.NONE) {
if (last.num1 != '0') {
last.num2 = '1';
last.operation = Calculations.ADD;
last.closed = true;
}
items.add(last);
} else if (last.operation == Calculations.MULTIPLY) {
if (last.num2 == null) {
last.num2 = '1';
last.operation = Calculations.ADD;
}
last.closed = true;
items.add(last);
} else {
last.closed = true;
items.add(last);
}
}
}
return [...items];
}
static List<CalcModel> _setDot({String value, List<CalcModel> items}) {
if (items.isNotEmpty) {
CalcModel last = items.removeLast();
if (last.operation == Calculations.NONE) {
if (last.num1?.contains('.') == false) {
last.num1 += '.';
}
last.operation = Calculations.NONE;
items.add(last);
} else if (last.operation == Calculations.ADD) {
items.add(last);
items.add(CalcModel(num1: '0.', operation: Calculations.NONE));
} else if (last.operation == Calculations.MULTIPLY) {
if (last.num2 == null) {
last.num2 += '0.';
} else {
if (last.num2?.contains('.') == false) {
last.num2 += '.';
}
}
last.operation = Calculations.MULTIPLY;
items.add(last);
}
} else {
items.add(CalcModel(num1: '0.', operation: Calculations.NONE));
}
return [...items];
}
static List<CalcModel> _setClean({String value, List<CalcModel> items}) {
return [];
}
static List<CalcModel> _setEqual({String value, List<CalcModel> items}) {
if (items.isNotEmpty) {
CalcModel last = items.removeLast();
last.operation = Calculations.EQUAL;
items.add(last);
}
return [...items];
}
static List<CalcModel> _setMultiply({String value, List<CalcModel> items}) {
if (items.isNotEmpty) {
CalcModel last = items.removeLast();
if (last.closed) {
items.add(last);
} else {
if (last.operation == Calculations.NONE) {
if (last.num1 != '0') {
last.operation = Calculations.MULTIPLY;
last.num2 = null;
}
items.add(last);
} else if (last.operation == Calculations.MULTIPLY) {
if (last.num2 != '0') {
last.closed = true;
}
items.add(last);
}
}
}
return [...items];
}
static List<CalcModel> _setBackward({String value, List<CalcModel> items}) {
if (items.isNotEmpty) {
CalcModel last = items.removeLast();
}
return [...items];
} }
} }

View File

@ -1,3 +1,5 @@
import 'dart:math';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
class NumberDisplay extends StatelessWidget { class NumberDisplay extends StatelessWidget {
@ -5,18 +7,44 @@ class NumberDisplay extends StatelessWidget {
final String value; final String value;
GlobalKey stickyKey = GlobalKey();
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Padding( return Expanded(
padding: EdgeInsets.all(20), child: Padding(
child: Row( padding: const EdgeInsets.only(left: 20.0, right: 20.0, top: 20.0 ),
children: <Widget>[ child: Container(
Text( key: stickyKey,
value, alignment: Alignment.topLeft,
style: TextStyle(fontSize: 40, fontWeight: FontWeight.bold), child: AnimatedDefaultTextStyle(
duration: const Duration(milliseconds: 200),
style: TextStyle(
fontSize: fontSizeCalc(value: value),
fontWeight: FontWeight.bold,
color: Colors.black,
), ),
], child: Text(
mainAxisAlignment: MainAxisAlignment.end, value,
)); ),
),
)),
);
}
double fontSizeCalc({ String value = " " }) {
const double result = 40.0;
try {
const double global = 100000.0;
double scale = (global / value.length);
final pixelOfLetter = sqrt(scale);
final pixelOfLetterP = pixelOfLetter - (pixelOfLetter * 5) / 100;
if(pixelOfLetterP> result){
return result;
}
return pixelOfLetterP;
} catch(e) {
return result;
}
} }
} }

View File

@ -2,9 +2,11 @@ import 'package:aman_kassa_flutter/core/locator.dart';
import 'package:aman_kassa_flutter/core/models/dialog_models.dart'; import 'package:aman_kassa_flutter/core/models/dialog_models.dart';
import 'package:aman_kassa_flutter/core/services/dialog_service.dart'; import 'package:aman_kassa_flutter/core/services/dialog_service.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
class DialogManager extends StatefulWidget { class DialogManager extends StatefulWidget {
final Widget child; final Widget child;
DialogManager({Key key, this.child}) : super(key: key); DialogManager({Key key, this.child}) : super(key: key);
_DialogManagerState createState() => _DialogManagerState(); _DialogManagerState createState() => _DialogManagerState();
@ -12,11 +14,19 @@ class DialogManager extends StatefulWidget {
class _DialogManagerState extends State<DialogManager> { class _DialogManagerState extends State<DialogManager> {
DialogService _dialogService = locator<DialogService>(); DialogService _dialogService = locator<DialogService>();
TextEditingController controller;
@override @override
void initState() { void initState() {
super.initState(); super.initState();
_dialogService.registerDialogListener(_showDialog); controller = new TextEditingController();
_dialogService.registerDialogListener(_showDialog, _showDialogInput);
}
@override
void dispose() {
controller.dispose();
super.dispose();
} }
@override @override
@ -50,4 +60,44 @@ class _DialogManagerState extends State<DialogManager> {
], ],
)); ));
} }
void _showDialogInput(DialogRequest request) {
var isConfirmationDialog = request.cancelTitle != null;
controller.clear();
showDialog(
context: context,
builder: (context) => AlertDialog(
title: Text(request.title),
content: Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Text(request.description),
TextField(
controller: controller,
keyboardType: TextInputType.number,
inputFormatters: <TextInputFormatter>[
WhitelistingTextInputFormatter(RegExp("^[0-9.]*")),
],
)
],
),
actions: <Widget>[
if (isConfirmationDialog)
FlatButton(
child: Text(request.cancelTitle),
onPressed: () {
_dialogService
.dialogComplete(DialogResponse(confirmed: false));
},
),
FlatButton(
child: Text(request.buttonTitle),
onPressed: () {
_dialogService
.dialogComplete(DialogResponse(confirmed: true, responseText: controller.text));
},
),
],
));
}
} }

View File

@ -0,0 +1,64 @@
import 'package:aman_kassa_flutter/shared/app_colors.dart';
import 'package:aman_kassa_flutter/shared/shared_styles.dart';
import 'package:flutter/material.dart';
/// A button that shows a busy indicator in place of title
class AmanIconButton extends StatefulWidget {
final bool busy;
final String title;
final Function onPressed;
final bool enabled;
final Color mainColor;
final IconData icon;
const AmanIconButton(
{
@required this.title,
this.busy = false,
@required this.onPressed,
this.enabled = true,
this.mainColor,
@required this.icon
});
@override
_AmanIconButtonState createState() => _AmanIconButtonState();
}
class _AmanIconButtonState extends State<AmanIconButton> {
@override
Widget build(BuildContext context) {
return GestureDetector(
child: InkWell(
onTap: widget.busy ? () {} : widget.onPressed,
child: Container(
//height: 75,
width: 120,
alignment: Alignment.center,
padding: EdgeInsets.symmetric(
horizontal: 25,
vertical: 15),
decoration: BoxDecoration(
//color: widget.enabled ? ( whiteColor ) : blueColorLigth,
borderRadius: BorderRadius.circular(50),
//boxShadow: [buttonShadowBox],
),
child: Column(
children: <Widget>[
(!widget.busy
? Icon(
widget.icon,
color: widget.mainColor,
size: 36,
)
: CircularProgressIndicator(
strokeWidth: 3,
valueColor: AlwaysStoppedAnimation<Color>(widget.mainColor))),
Text(widget.title, style: TextStyle(color: widget.mainColor, fontSize: 15, fontWeight: FontWeight.bold, ), textAlign: TextAlign.center,)
],
),
),
),
);
}
}

View File

@ -0,0 +1,38 @@
import 'package:aman_kassa_flutter/shared/app_colors.dart';
import 'package:aman_kassa_flutter/shared/shared_styles.dart';
import 'package:flutter/material.dart';
import 'package:material_design_icons_flutter/material_design_icons_flutter.dart';
/// A button that shows a busy indicator in place of title
class AmanIconButtonHorizontal extends StatefulWidget {
final String title;
final Function onPressed;
final Color activeColor;
final Color inactiveColor;
final bool selected;
final IconData icon;
const AmanIconButtonHorizontal(
{
@required this.title,
this.onPressed,
this.activeColor = primaryColor,
this.inactiveColor = Colors.black26,
this.selected = false,
@required this.icon
});
@override
_AmanIconButtonHorizontalState createState() => _AmanIconButtonHorizontalState();
}
class _AmanIconButtonHorizontalState extends State<AmanIconButtonHorizontal> {
@override
Widget build(BuildContext context) {
return GestureDetector(
child: InkWell(
onTap: widget.onPressed,
child: Row( mainAxisAlignment: MainAxisAlignment.end, children: <Widget>[ Icon(widget.icon , color: widget.selected ? widget.activeColor : widget.inactiveColor ), Text(widget.title, style: TextStyle( color: widget.selected ? widget.activeColor : widget.inactiveColor, fontWeight: FontWeight.w800 ) )],),
),
);
}
}

View File

@ -25,22 +25,27 @@ class BusyButton extends StatefulWidget {
class _BusyButtonState extends State<BusyButton> { class _BusyButtonState extends State<BusyButton> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return GestureDetector( return AnimatedContainer(
onTap: widget.onPressed,
child: InkWell(
child: AnimatedContainer(
height: widget.busy ? 40 : null,
width: widget.busy ? 40 : null,
duration: const Duration(milliseconds: 300), duration: const Duration(milliseconds: 300),
alignment: Alignment.center,
padding: EdgeInsets.symmetric(
horizontal: widget.busy ? 10 : 25,
vertical: widget.busy ? 10 : 15),
decoration: BoxDecoration( decoration: BoxDecoration(
color: widget.enabled ? ( widget.mainColor ?? primaryColor) : blueColorLigth, color: widget.enabled ? ( widget.mainColor ?? primaryColor) : blueColorLigth,
borderRadius: BorderRadius.circular(7), borderRadius: BorderRadius.circular(7),
boxShadow: [mainShadowBox] boxShadow: [
cardShadowBox
]
), ),
child: Material(
type: MaterialType.transparency,
child: InkWell(
onTap: widget.busy ? () {} : widget.onPressed,
child: AnimatedContainer(
height: widget.busy ? 40 : 40,
//width: widget.busy ? 40 : 40,
duration: const Duration(milliseconds: 300),
alignment: Alignment.center,
margin: EdgeInsets.symmetric(
horizontal: widget.busy ? 10 : 25,
vertical: widget.busy ? 10 : 15),
child: !widget.busy child: !widget.busy
? Text( ? Text(
widget.title, widget.title,
@ -51,6 +56,7 @@ class _BusyButtonState extends State<BusyButton> {
valueColor: AlwaysStoppedAnimation<Color>(Colors.white)), valueColor: AlwaysStoppedAnimation<Color>(Colors.white)),
), ),
), ),
),
); );
} }
} }

View File

@ -1,3 +1,4 @@
import 'package:aman_kassa_flutter/shared/app_colors.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
class Dialogs { class Dialogs {
@ -17,7 +18,7 @@ class Dialogs {
child: Column(children: [ child: Column(children: [
CircularProgressIndicator(), CircularProgressIndicator(),
SizedBox(height: 10,), SizedBox(height: 10,),
Text("Please Wait....",style: TextStyle(color: Colors.blueAccent),) Text("Подождите выполняеться операция с сервером", textAlign: TextAlign.center, style: TextStyle(color: Colors.grey.shade300, fontWeight: FontWeight.bold, fontSize: 15),)
]), ]),
) )
])); ]));

View File

@ -130,6 +130,13 @@ packages:
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "2.1.12" version: "2.1.12"
intl:
dependency: "direct main"
description:
name: intl
url: "https://pub.dartlang.org"
source: hosted
version: "0.16.1"
logger: logger:
dependency: "direct main" dependency: "direct main"
description: description:

View File

@ -24,6 +24,7 @@ dependencies:
flutter_boom_menu: ^1.0.2 flutter_boom_menu: ^1.0.2
sliding_up_panel: ^1.0.2 sliding_up_panel: ^1.0.2
material_design_icons_flutter: ^4.0.5345 material_design_icons_flutter: ^4.0.5345
intl: ^0.16.1
dev_dependencies: dev_dependencies:
flutter_test: flutter_test:
sdk: flutter sdk: flutter