pre release

4.4
Serik.Uvaissov 2020-06-25 11:39:17 +06:00
parent 2e2033fec1
commit d3d983ba3f
24 changed files with 680 additions and 137 deletions

View File

@ -47,7 +47,7 @@ android {
defaultConfig { defaultConfig {
// TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
applicationId "com.example.aman_kassa_flutter" applicationId "com.example.aman_kassa_flutter"
minSdkVersion 16 minSdkVersion 18
targetSdkVersion 28 targetSdkVersion 28
versionCode flutterVersionCode.toInteger() versionCode flutterVersionCode.toInteger()
versionName flutterVersionName versionName flutterVersionName

View File

@ -6,9 +6,13 @@
additional functionality it is fine to subclass or reimplement additional functionality it is fine to subclass or reimplement
FlutterApplication and put your custom class here. --> FlutterApplication and put your custom class here. -->
<uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.CAMERA" />
<application <application
android:name="io.flutter.app.FlutterApplication" android:name="io.flutter.app.FlutterApplication"
android:label="aman_kassa_flutter" android:label="Аман Касса"
android:icon="@mipmap/ic_launcher" android:icon="@mipmap/ic_launcher"
android:usesCleartextTraffic="true"> android:usesCleartextTraffic="true">
<activity <activity

View File

@ -1,12 +1,83 @@
package com.example.aman_kassa_flutter package com.example.aman_kassa_flutter
import androidx.annotation.NonNull; import android.content.Context
import android.content.ContextWrapper
import android.content.Intent
import android.content.IntentFilter
import android.content.pm.PackageManager
import android.net.Uri
import android.os.BatteryManager
import android.os.Build.VERSION
import android.os.Build.VERSION_CODES
import androidx.annotation.NonNull
import io.flutter.embedding.android.FlutterActivity import io.flutter.embedding.android.FlutterActivity
import io.flutter.embedding.engine.FlutterEngine import io.flutter.embedding.engine.FlutterEngine
import io.flutter.plugin.common.MethodChannel
import io.flutter.plugins.GeneratedPluginRegistrant import io.flutter.plugins.GeneratedPluginRegistrant
class MainActivity: FlutterActivity() { class MainActivity: FlutterActivity() {
private val CHANNEL = "samples.flutter.dev/battery"
override fun configureFlutterEngine(@NonNull flutterEngine: FlutterEngine) { override fun configureFlutterEngine(@NonNull flutterEngine: FlutterEngine) {
GeneratedPluginRegistrant.registerWith(flutterEngine); GeneratedPluginRegistrant.registerWith(flutterEngine);
MethodChannel(flutterEngine.dartExecutor.binaryMessenger, CHANNEL).setMethodCallHandler {
// Note: this method is invoked on the main thread.
call, result ->
if (call.method == "getBatteryLevel") {
val batteryLevel = getBatteryLevel()
if (batteryLevel != -1) {
result.success(batteryLevel)
} else {
result.error("UNAVAILABLE", "Battery level not available.", null)
}
} else if (call.method == "sendMessage") {
val batteryLevel = sendMessage()
if (batteryLevel != -1) {
result.success(batteryLevel)
} else {
result.error("UNAVAILABLE", "Battery level not available.", null)
}
} else {
result.notImplemented()
}
}
}
private fun getBatteryLevel(): Int {
val batteryLevel: Int
if (VERSION.SDK_INT >= VERSION_CODES.LOLLIPOP) {
val batteryManager = getSystemService(Context.BATTERY_SERVICE) as BatteryManager
batteryLevel = batteryManager.getIntProperty(BatteryManager.BATTERY_PROPERTY_CAPACITY)
} else {
val intent = ContextWrapper(applicationContext).registerReceiver(null, IntentFilter(Intent.ACTION_BATTERY_CHANGED))
batteryLevel = intent!!.getIntExtra(BatteryManager.EXTRA_LEVEL, -1) * 100 / intent.getIntExtra(BatteryManager.EXTRA_SCALE, -1)
}
println("batteryLevel");
println(batteryLevel);
return batteryLevel
}
private fun sendMessage(): Int {
val packageManager: PackageManager = context.packageManager
val i = Intent(Intent.ACTION_VIEW)
try {
val mobileNo: String = "77774904900" //call.argument("mobileNo")
val message: String = "Hello world" //call.argument("message")
//https://wa.me/919167370647?text=Yes%20We'll%20do%20this%20in%20frag4%20inOCW
println("mobileNo: $mobileNo message: $message")
val url = "https://wa.me/" + mobileNo.trim { it <= ' ' } + "?text=" + message.trim { it <= ' ' }
i.setPackage("com.whatsapp")
i.data = Uri.parse(url)
if (i.resolveActivity(packageManager) != null) {
context.startActivity(i)
}
println("finish method - 2")
} catch (e: Exception) {
e.printStackTrace()
}
return 25
} }
} }

View File

@ -1,5 +1,5 @@
buildscript { buildscript {
ext.kotlin_version = '1.3.50' ext.kotlin_version = '1.3.61'
repositories { repositories {
google() google()
jcenter() jcenter()

View File

@ -2,6 +2,8 @@
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0"> <plist version="1.0">
<dict> <dict>
<key>NSCameraUsageDescription</key>
<string>Camera permission is required for barcode and qr-code scanning.</string>
<key>CFBundleDevelopmentRegion</key> <key>CFBundleDevelopmentRegion</key>
<string>$(DEVELOPMENT_LANGUAGE)</string> <string>$(DEVELOPMENT_LANGUAGE)</string>
<key>CFBundleExecutable</key> <key>CFBundleExecutable</key>

View File

@ -9,14 +9,27 @@ class User {
User({this.email, this.fullName, this.name, this.token, this.appCompanyId, this.kassaId}); User({this.email, this.fullName, this.name, this.token, this.appCompanyId, this.kassaId});
factory User.fromJson(Map<String, dynamic> json) { static User fromJson(Map<String, dynamic> json) {
return User ( return json != null
? User (
name: json['name'], name: json['name'],
email: json['mail'], email: json['mail'],
token: json['api_token'], token: json['api_token'],
fullName: json['fullname'], fullName: json['fullname'],
appCompanyId: json['app_company_id'] as int, appCompanyId: json['app_company_id'] as int,
kassaId: json['kassa_id'] as int, kassaId: json['kassa_id'] as int,
); )
} : null;
}
dynamic toJson() {
return {
"name": name,
"mail": email,
"api_token": token,
"fullname": fullName,
"app_company_id": appCompanyId,
"kassa_id": kassaId
};
}
} }

View File

@ -2,10 +2,14 @@ import 'dart:convert';
import 'dart:io'; 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:device_info/device_info.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/smena.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/dialog_service.dart';
import 'package:aman_kassa_flutter/core/services/navigator_service.dart';
import 'package:aman_kassa_flutter/core/locator.dart';
import '../models/auth_response.dart'; import '../models/auth_response.dart';
import 'package:http/http.dart' as http; import 'package:http/http.dart' as http;
@ -13,6 +17,8 @@ import 'package:http/http.dart' as http;
/// The service responsible for networking requests /// The service responsible for networking requests
class ApiService extends BaseService { class ApiService extends BaseService {
static const endpoint = 'https://kassa-test.aman.com.kz/ru/api/v2'; static const endpoint = 'https://kassa-test.aman.com.kz/ru/api/v2';
final NavigatorService _navigatorService = locator<NavigatorService>();
final DialogService _dialogService = locator<DialogService>();
var client = new http.Client(); var client = new http.Client();
@ -27,16 +33,27 @@ class ApiService extends BaseService {
return aman.body; return aman.body;
} }
Future<AuthBody> authenticate_token(String token, { bool statusCheck = true}) async {
Map<String, String> requestBody = <String, String>{
'token': token
};
String response = await requestFormData('/activate_token', requestBody, statusCheck: statusCheck );
AuthResponse aman = AuthResponse.fromJson(json.decode(response));
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);
return Response.fromJson(json.decode(response), Message.fromJson); return Response.fromJson(json.decode(response), Message.fromJson);
} }
Future<Response<Message>> logout(String token) async { Future<Response<dynamic>> 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);
return Response.fromJson(json.decode(response), Message.fromJson); print(json.decode(response));
return Response.fromJsonDynamic(json.decode(response));
} }
Future<Response<dynamic>> money(String token) async { Future<Response<dynamic>> money(String token) async {
@ -102,10 +119,28 @@ class ApiService extends BaseService {
Future<String> requestFormData(String point, Map<String, String> requestBody, { bool statusCheck = true } ) async { Future<String> requestFormData(String point, Map<String, String> requestBody, { bool statusCheck = true } ) async {
DeviceInfoPlugin deviceInfo = DeviceInfoPlugin();
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"
}; };
if(Platform.isAndroid) {
AndroidDeviceInfo androidInfo = await deviceInfo.androidInfo;
print(androidInfo.model);
headers.addAll(<String, String>{
HttpHeaders.userAgentHeader: androidInfo.model,
});
}
if(Platform.isIOS) {
IosDeviceInfo iosInfo = await deviceInfo.iosInfo;
print(iosInfo.utsname.machine);
headers.addAll(<String, String>{
HttpHeaders.userAgentHeader: iosInfo.utsname.machine,
});
}
var uri = Uri.parse('$endpoint$point'); var uri = Uri.parse('$endpoint$point');
var request = http.MultipartRequest('POST', uri) var request = http.MultipartRequest('POST', uri)
@ -118,7 +153,8 @@ class ApiService extends BaseService {
if(statusCheck) { //Проверка на авторизованный запрос, необязательный параметр if(statusCheck) { //Проверка на авторизованный запрос, необязательный параметр
Response check = Response.fromJsonDynamic(json.decode(body)); Response check = Response.fromJsonDynamic(json.decode(body));
if (!check.operation && check.status == 401) { if (!check.operation && check.status == 401) {
print('object'); _dialogService.showDialog(description: 'Необходимо пройти повторную авторизацию');
_navigatorService.replace(LoginViewRoute);
} }
} }
return body; return body;

View File

@ -5,6 +5,7 @@ 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/calc_model.dart';
import 'package:aman_kassa_flutter/core/models/check_data.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/check_item.dart';
import 'package:aman_kassa_flutter/core/models/product_dao.dart'; import 'package:aman_kassa_flutter/core/models/product_dao.dart';
@ -12,6 +13,7 @@ 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/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/constants/operation_const.dart';
import 'package:aman_kassa_flutter/redux/constants/setting_const.dart';
import 'package:aman_kassa_flutter/redux/store.dart'; import 'package:aman_kassa_flutter/redux/store.dart';
import 'ApiService.dart'; import 'ApiService.dart';
@ -38,9 +40,7 @@ class DataService extends BaseService {
} }
CheckData _transformProductsToCheckData( CheckData _transformProductsToCheckData(
{String paymentType, {String paymentType, String tradeType, List<ProductDao> items}) {
String tradeType,
List<ProductDao> items}) {
List<CheckItem> itemsList = []; List<CheckItem> itemsList = [];
int iterator = 1; int iterator = 1;
num summ = 0.0; num summ = 0.0;
@ -67,16 +67,52 @@ class DataService extends BaseService {
return checkData; return checkData;
} }
CheckData _transformCalcModelToCheckData(
{String paymentType, String tradeType, List<CalcModel> items}) {
List<CheckItem> itemsList = [];
int iterator = 1;
num summ = 0.0;
items.forEach((el) {
int articul = iterator;
CheckItem item = CheckItem(
name: 'Позиция $iterator',
cnt: el.num2 != null ? double.parse(el.num2) : 1.0,
price: double.parse(el.num1) ,
articul: articul);
summ += item.cnt * item.price;
itemsList.add(item);
iterator++;
});
CheckData checkData = CheckData(type: tradeType, items: itemsList);
if ((paymentType ?? 'cash') == 'card') {
checkData.card = summ;
}
print(checkData);
return checkData;
}
Future<Response<dynamic>> sellOrReturn( Future<Response<dynamic>> sellOrReturn(
{String paymentType, {String paymentType,
String tradeType, String tradeType,
String token, String token,
List<ProductDao> items, List<ProductDao> kassaItems,
String operationType}) async { List<CalcModel> calcItems,
String operationType,
String mode}) async {
try { try {
CheckData checkData = _transformProductsToCheckData( String data;
paymentType: paymentType, tradeType: tradeType, items: items); if(mode == SettingModeKassa) {
String data = jsonEncode(checkData.toJson()); CheckData checkData = _transformProductsToCheckData(
paymentType: paymentType, tradeType: tradeType, items: kassaItems);
data = jsonEncode(checkData.toJson());
} else if(mode == SettingModeCalc) {
CheckData checkData = _transformCalcModelToCheckData(
paymentType: paymentType, tradeType: tradeType, items: calcItems);
data = jsonEncode(checkData.toJson());
}
log.i('token: $token'); log.i('token: $token');
log.i('data: $data'); log.i('data: $data');
Response<dynamic> response = await (operationType == OperationTypePay Response<dynamic> response = await (operationType == OperationTypePay

View File

@ -32,6 +32,10 @@ Future<void> setEqual(Store<AppState> store) async {
store.dispatch(SetCalcStateAction(CalcState(isEqual: true))); store.dispatch(SetCalcStateAction(CalcState(isEqual: true)));
} }
Future<void> cleanCalcItems(Store<AppState> store) async {
store.dispatch(SetCalcStateAction(CalcState(calcItems: [])));
}
ThunkAction<AppState> onTapAction(String value) { ThunkAction<AppState> onTapAction(String value) {
return (Store<AppState> store) async { return (Store<AppState> store) async {

View File

@ -38,6 +38,10 @@ Future<void> backBottomElement(Store<AppState> store) async {
} }
} }
Future<void> cleanKassaItems(Store<AppState> store) async {
store.dispatch(SetKassaStateAction(KassaState(kassaItems: [])));
}
ThunkAction<AppState> addCustomProductToKassaItems(String name, int count, double price, double total) { ThunkAction<AppState> addCustomProductToKassaItems(String name, int count, double price, double total) {
return (Store<AppState> store) async { return (Store<AppState> store) async {
List<ProductDao> items = store.state.kassaState.kassaItems; List<ProductDao> items = store.state.kassaState.kassaItems;

View File

@ -10,6 +10,7 @@ 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';
import 'package:aman_kassa_flutter/core/services/dialog_service.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/core/services/navigator_service.dart';
import 'package:aman_kassa_flutter/redux/constants/auth_type_const.dart';
import 'package:aman_kassa_flutter/redux/state/user_state.dart'; import 'package:aman_kassa_flutter/redux/state/user_state.dart';
import 'package:redux/redux.dart'; import 'package:redux/redux.dart';
import 'package:meta/meta.dart'; import 'package:meta/meta.dart';
@ -28,8 +29,14 @@ final DialogService _dialogService = locator<DialogService>();
Future<void> checkUserAction(Store<AppState> store) async { Future<void> checkUserAction(Store<AppState> store) async {
store.dispatch(SetUserStateAction(UserState(isLoading: true))); store.dispatch(SetUserStateAction(UserState(isLoading: true)));
try { try {
Response<Message> session = await _api.isActive('test'); String token = store.state.userState.user?.token;
bool isAuthenticated = "OK" == session.body.message; bool isAuthenticated = false;
if(token!=null) {
Response<Message> session = await _api.isActive(token);
isAuthenticated = "OK" == session.body.message;
} else {
await Future.delayed(Duration(milliseconds: 100));
}
store.dispatch( store.dispatch(
SetUserStateAction( SetUserStateAction(
UserState( UserState(
@ -41,14 +48,59 @@ Future<void> checkUserAction(Store<AppState> store) async {
if(!isAuthenticated){ if(!isAuthenticated){
_navigation.replace(LoginViewRoute); _navigation.replace(LoginViewRoute);
} else {
_navigation.replace(HomeViewRoute);
} }
} catch (error) {
print(error);
store.dispatch(SetUserStateAction(UserState(isLoading: false)));
}
}
Future<void> logoutAction(Store<AppState> store) async {
try {
store.dispatch(
SetUserStateAction(
UserState(
isLoading: false,
isAuthenticated: false,
user: User(),
),
),
);
_navigation.replace(LoginViewRoute);
} catch (error) { } catch (error) {
store.dispatch(SetUserStateAction(UserState(isLoading: false))); store.dispatch(SetUserStateAction(UserState(isLoading: false)));
} }
} }
ThunkAction<AppState> authenticateToken(String token) {
return (Store<AppState> store) async {
store.dispatch(SetUserStateAction(UserState(isLoading: true)));
try {
AuthBody result = await _api.authenticate_token(token, statusCheck: false);
store.dispatch(SetUserStateAction(UserState(
isLoading: false,
loginFormMessage: LoginFormMessage(email: result.email?.join(","), password: result.password?.join(","), message: result.message),
user: result.user,
authenticateType: AuthenticateTypeQr,
isAuthenticated: result.user != null,
)));
if(result.user == null && result.message!=null){
_dialogService.showDialog(title: 'Warning', buttonTitle: 'Ok', description: result.message);
}
if(result.user!=null) {
_navigation.replace(HomeViewRoute);
}
} catch(e) {
print(e);
store.dispatch(SetUserStateAction(UserState(isLoading: false)));
}
};
}
ThunkAction<AppState> authenticate(String email, String password) { ThunkAction<AppState> authenticate(String email, String password) {
return (Store<AppState> store) async { return (Store<AppState> store) async {
@ -58,7 +110,11 @@ ThunkAction<AppState> authenticate(String email, String password) {
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),
user: result.user user: result.user,
login: email,
password: password,
authenticateType: AuthenticateTypeLogin,
isAuthenticated: result.user != null,
))); )));
if(result.user == null && result.message!=null){ if(result.user == null && result.message!=null){
_dialogService.showDialog(title: 'Warning', buttonTitle: 'Ok', description: result.message); _dialogService.showDialog(title: 'Warning', buttonTitle: 'Ok', description: result.message);

View File

@ -0,0 +1,2 @@
const String AuthenticateTypeQr = 'AuthenticateTypeQr';
const String AuthenticateTypeLogin = 'AuthenticateTypeLogin';

View File

@ -8,8 +8,14 @@ class SettingState {
SettingState({this.mode, this.tradeType}); SettingState({this.mode, this.tradeType});
factory SettingState.initial() => SettingState(mode: SettingModeCalc, tradeType: SettingTradeTypeGood); //read hive
factory SettingState.initial(SettingState payload) {
return SettingState(
mode: payload?.mode ?? SettingModeCalc,
tradeType: payload?.tradeType ?? SettingTradeTypeGood);
}
//write hive
SettingState copyWith({ SettingState copyWith({
@required mode, @required mode,
@required tradeType, @required tradeType,
@ -19,4 +25,17 @@ class SettingState {
tradeType: tradeType ?? this.tradeType, tradeType: tradeType ?? this.tradeType,
); );
} }
static SettingState fromJson(dynamic json) {
return json != null
? SettingState(
tradeType: json['tradeType'],
mode: json['mode'],
)
: null;
}
dynamic toJson() {
return {"tradeType": tradeType, "mode": mode};
}
} }

View File

@ -7,49 +7,85 @@ class UserState {
final bool isError; final bool isError;
final bool isLoading; final bool isLoading;
final bool isAuthenticated; final bool isAuthenticated;
final String authenticateType;
final String login;
final String password;
final LoginFormMessage loginFormMessage; final LoginFormMessage loginFormMessage;
final User user; final User user;
final Smena smena; final Smena smena;
UserState({ UserState(
this.isError, {this.isError,
this.isLoading, this.isLoading,
this.isAuthenticated, this.isAuthenticated,
this.user, this.authenticateType,
this.loginFormMessage, this.login,
this.smena this.password,
}); this.user,
this.loginFormMessage,
this.smena});
factory UserState.initial() => UserState( factory UserState.initial(UserState payload) => UserState(
isLoading: false, isLoading: false,
isError: false, isError: false,
isAuthenticated: false, isAuthenticated: false,
loginFormMessage: LoginFormMessage(), loginFormMessage: LoginFormMessage(),
smena: Smena(), smena: Smena(),
); user: payload?.user ?? User(),
authenticateType: payload?.authenticateType ?? null,
login: payload?.login ?? null,
password: payload?.password ?? null,
);
UserState copyWith({ UserState copyWith(
@required bool isError, {@required bool isError,
@required bool isLoading, @required bool isLoading,
@required User user, @required User user,
@required bool isAuthenticated, @required bool isAuthenticated,
@required LoginFormMessage loginFormMessage, @required LoginFormMessage loginFormMessage,
@required Smena smena, @required Smena smena,
}) { @required String authenticateType,
@required String login,
@required String password,
}) {
return UserState( return UserState(
isError: isError ?? this.isError, isError: isError ?? this.isError,
isLoading: isLoading ?? this.isLoading, isLoading: isLoading ?? this.isLoading,
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, smena: smena ?? this.smena,
authenticateType: authenticateType ?? this.authenticateType,
login: login ?? this.login,
password: password ?? this.password,
); );
} }
static UserState fromJson(dynamic json) {
return json != null
? UserState(
user: User.fromJson(json['user']),
authenticateType: json['authenticateType'],
login: json['login'],
password: json['password']
)
: null;
}
dynamic toJson() {
return {
"user": user != null ? user.toJson() : null,
"authenticateType": authenticateType,
"login": login,
"password": password,
};
}
} }
class LoginFormMessage { class LoginFormMessage {
final String email; final String email;
final String password; final String password;
final String message; final String message;
LoginFormMessage({this.email, this.password, this.message}); LoginFormMessage({this.email, this.password, this.message});
} }

View File

@ -11,7 +11,10 @@ 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_persist_flutter/redux_persist_flutter.dart';
import 'package:redux_thunk/redux_thunk.dart'; import 'package:redux_thunk/redux_thunk.dart';
import 'package:redux_persist/redux_persist.dart';
import 'dart:io';
import 'actions/calc_actions.dart'; import 'actions/calc_actions.dart';
@ -46,10 +49,10 @@ class AppState {
final CalcState calcState; final CalcState calcState;
AppState({ AppState({
@required this.userState, this.userState,
@required this.kassaState, this.kassaState,
@required this.settingState, this.settingState,
@required this.calcState, this.calcState,
}); });
//stable work //stable work
@ -66,6 +69,23 @@ class AppState {
calcState: calcState ?? this.calcState, calcState: calcState ?? this.calcState,
); );
} }
static AppState fromJson(dynamic json){
print(json);
return json !=null
? AppState(
settingState: SettingState.fromJson(json['settingState']),
userState: UserState.fromJson(json['userState']),
)
: null;
}
dynamic toJson() {
return {
"settingState": settingState.toJson(),
"userState" : userState.toJson(),
};
}
} }
class Redux { class Redux {
@ -81,14 +101,22 @@ class Redux {
//initial context //initial context
static Future<void> init() async { static Future<void> init() async {
final userStateInitial = UserState.initial(); // Create Persistor
final persist = Persistor<AppState>(
storage: FlutterStorage(), // Or use other engines
serializer: JsonSerializer<AppState>(AppState.fromJson), // Or use other serializers
);
final initialState = await persist.load();
final userStateInitial = UserState.initial(initialState?.userState);
final kassaStateInitial = KassaState.initial(); final kassaStateInitial = KassaState.initial();
final settingStateInitial = SettingState.initial(); final settingStateInitial = SettingState.initial(initialState?.settingState);
final calcStateInitial = CalcState.initial(); final calcStateInitial = CalcState.initial();
_store = Store<AppState>( _store = Store<AppState>(
appReducer, appReducer,
middleware: [thunkMiddleware], middleware: [thunkMiddleware, persist.createMiddleware() ],
initialState: AppState( initialState: AppState(
userState: userStateInitial, userState: userStateInitial,
kassaState: kassaStateInitial, kassaState: kassaStateInitial,

View File

@ -1,10 +1,16 @@
import 'dart:convert'; import 'dart:convert';
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/widgets/fields/busy_button.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:material_design_icons_flutter/material_design_icons_flutter.dart';
//import 'package:flutter/services.dart';
class ImageShowContainer extends StatelessWidget { class ImageShowContainer extends StatelessWidget {
final ImageShowModel data; final ImageShowModel data;
ImageShowContainer(this.data); ImageShowContainer(this.data);
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Scaffold( return Scaffold(
@ -13,12 +19,12 @@ class ImageShowContainer extends StatelessWidget {
title: Text(data.title), title: Text(data.title),
), ),
body: ListView( body: ListView(
children: <Widget>[ children: <Widget>[imageFromBase64String(data.data)],
imageFromBase64String(data.data)
],
), ),
floatingActionButton: MyFloatingActionButton(),
); );
} }
} }
Padding imageFromBase64String(String base64String) { Padding imageFromBase64String(String base64String) {
@ -28,9 +34,99 @@ Padding imageFromBase64String(String base64String) {
); );
} }
class ImageShowModel { class ImageShowModel {
final String data; final String data;
final String title; final String title;
ImageShowModel(this.data, this.title); ImageShowModel(this.data, this.title);
}
class MyFloatingActionButton extends StatefulWidget {
@override
_MyFloatingActionButtonState createState() => _MyFloatingActionButtonState();
}
class _MyFloatingActionButtonState extends State<MyFloatingActionButton> {
bool showFab = true;
// String _batteryLevel = 'Unknown battery level.';
// static const platform = const MethodChannel('samples.flutter.dev/battery');
//
// Future<void> _getBatteryLevel() async {
// String batteryLevel;
// try {
// final int result = await platform.invokeMethod('sendMessage');
// print(result);
// batteryLevel = 'Battery level at $result % .';
// } on PlatformException catch (e) {
// batteryLevel = "Failed to get battery level: '${e.message}'.";
// }
//
// setState(() {
// _batteryLevel = batteryLevel;
// });
// }
@override
Widget build(BuildContext context) {
return showFab
? FloatingActionButton(
child: Icon(Icons.share),
onPressed: () {
var bottomSheetController = showBottomSheet(
context: context,
builder: (context) => Container(
padding: const EdgeInsets.symmetric(horizontal: 10.0 ),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.all(Radius.circular(15)),
boxShadow: [
BoxShadow(
blurRadius: 10, color: Colors.grey[300], spreadRadius: 5)
]),
//color: Colors.grey[900],
height: 280,
child: Column(
children: <Widget>[
verticalSpaceSmall,
BusyButton(title: 'Электронная почта', onPressed: () {} , mainColor: primaryColor, icon: Icons.mail, ),
verticalSpaceSmall,
BusyButton(title: 'WhatsApp', onPressed: () {} , mainColor: greenColor, icon: MdiIcons.whatsapp, ),
verticalSpaceSmall,
BusyButton(title: '', onPressed: () {} , mainColor: yellowColor, icon: Icons.share,),
],
)
));
showFoatingActionButton(false);
bottomSheetController.closed.then((value) {
showFoatingActionButton(true);
});
},
): Container() ;
}
void showFoatingActionButton(bool value) {
setState(() {
showFab = value;
});
}
}
class DecoratedTextField extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Container(
alignment: Alignment.centerLeft,
padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 10),
margin: const EdgeInsets.symmetric(horizontal: 10, vertical: 10),
decoration: BoxDecoration(
//color: fillColor, borderRadius: BorderRadius.circular(10)
),
child: TextField(
decoration: InputDecoration(
prefixIcon: Icon(Icons.mail_outline, color: primaryColor,),
labelStyle: TextStyle(color: primaryColor),
labelText: 'Отправить на Email',
),
));
}
} }

View File

@ -1,7 +1,12 @@
import 'package:aman_kassa_flutter/core/locator.dart'; import 'package:aman_kassa_flutter/core/locator.dart';
import 'package:aman_kassa_flutter/core/logger.dart'; import 'package:aman_kassa_flutter/core/logger.dart';
import 'package:aman_kassa_flutter/core/models/choice.dart'; import 'package:aman_kassa_flutter/core/models/choice.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/route_names.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/DataService.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/user_actions.dart';
import 'package:aman_kassa_flutter/redux/constants/setting_const.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/state/setting_state.dart';
@ -40,6 +45,8 @@ class _HomeViewState extends State<HomeView> {
PageController pageController; PageController pageController;
int selectedTabIndex; int selectedTabIndex;
DataService _dataService = locator<DataService>(); DataService _dataService = locator<DataService>();
ApiService _api = locator<ApiService>();
NavigatorService _navigatorService = locator<NavigatorService>();
final GlobalKey<State> _keyLoader = new GlobalKey<State>(); final GlobalKey<State> _keyLoader = new GlobalKey<State>();
@override @override
@ -58,7 +65,12 @@ class _HomeViewState extends State<HomeView> {
void _onSelectChoice(Choice choice) async { void _onSelectChoice(Choice choice) async {
if (choice.command == 'exit') { if (choice.command == 'exit') {
Dialogs.showLoadingDialog(context, _keyLoader);
Response<dynamic> result = await _api.logout(Redux.store.state.userState.user.token);
if(result.operation && result.status == 200) {
Redux.store.dispatch(logoutAction);
}
Navigator.of(_keyLoader.currentContext, rootNavigator: true).pop();
} 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); bool result = await _dataService.getDataFromServer(Redux.store.state.userState.user);

View File

@ -40,12 +40,11 @@ class CalculatorTab extends StatelessWidget {
Row( Row(
children: <Widget>[ children: <Widget>[
Expanded( Expanded(
child: RaisedButton( child: RaisedButton(
padding: EdgeInsets.all(10.0), padding: EdgeInsets.all(8.0),
color: redColor, color: redColor,
child: Text( child: Text(
"Возврат", "возврат",
style: buttonBigTitleTextStyle, style: buttonBigTitleTextStyle,
), ),
onPressed: () { onPressed: () {
@ -55,11 +54,11 @@ class CalculatorTab extends StatelessWidget {
), ),
Expanded( Expanded(
child: RaisedButton( child: RaisedButton(
padding: EdgeInsets.all(10.0), padding: EdgeInsets.all(8.0),
color: greenColor, color: greenColor,
child: Text( child: Text(
"Оплата", "оплата",
style: buttonBigTitleTextStyle, style: buttonBigTitleTextStyle,
), ),
onPressed: () { onPressed: () {

View File

@ -107,7 +107,7 @@ class KassaTab extends StatelessWidget {
padding: EdgeInsets.all(8), padding: EdgeInsets.all(8),
color: redColor, color: redColor,
child: Text( child: Text(
"Возврат", "возврат",
style: buttonBigTitleTextStyle, style: buttonBigTitleTextStyle,
), ),
onPressed: () { onPressed: () {
@ -123,7 +123,7 @@ class KassaTab extends StatelessWidget {
padding: EdgeInsets.all(8), padding: EdgeInsets.all(8),
color: greenColor, color: greenColor,
child: Text( child: Text(
"Оплата", "оплата",
style: buttonBigTitleTextStyle, style: buttonBigTitleTextStyle,
), ),
onPressed: () { onPressed: () {

View File

@ -1,3 +1,7 @@
import 'dart:ui';
import 'package:aman_kassa_flutter/core/locator.dart';
import 'package:aman_kassa_flutter/core/services/dialog_service.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/state/user_state.dart'; import 'package:aman_kassa_flutter/redux/state/user_state.dart';
import 'package:aman_kassa_flutter/redux/store.dart'; import 'package:aman_kassa_flutter/redux/store.dart';
@ -5,9 +9,14 @@ 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/widgets/fields/busy_button.dart'; import 'package:aman_kassa_flutter/widgets/fields/busy_button.dart';
import 'package:aman_kassa_flutter/widgets/fields/input_field.dart'; import 'package:aman_kassa_flutter/widgets/fields/input_field.dart';
import 'package:aman_kassa_flutter/widgets/fields/text_link.dart'; import 'package:barcode_scan/gen/protos/protos.pb.dart';
import 'package:barcode_scan/gen/protos/protos.pbenum.dart';
import 'package:barcode_scan/model/scan_options.dart';
import 'package:barcode_scan/platform_wrapper.dart';
import 'package:flutter/services.dart';
import 'package:flutter_redux/flutter_redux.dart'; import 'package:flutter_redux/flutter_redux.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:material_design_icons_flutter/material_design_icons_flutter.dart';
class LoginView extends StatelessWidget { class LoginView extends StatelessWidget {
final emailController = TextEditingController(text: 'test@kkm-kassa.kz'); final emailController = TextEditingController(text: 'test@kkm-kassa.kz');
@ -15,10 +24,7 @@ class LoginView extends StatelessWidget {
final FocusNode passwordNode = new FocusNode(); final FocusNode passwordNode = new FocusNode();
final GlobalKey<ScaffoldState> _scaffoldKey = new GlobalKey<ScaffoldState>(); final GlobalKey<ScaffoldState> _scaffoldKey = new GlobalKey<ScaffoldState>();
final DialogService _dialogService = locator<DialogService>();
_pressBtnEnter() async {
Redux.store.dispatch(authenticate(emailController.text, passwordController.text));
}
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
@ -35,11 +41,17 @@ class LoginView extends StatelessWidget {
mainAxisAlignment: MainAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[ children: <Widget>[
SizedBox( Stack(
height: 150, alignment: Alignment.bottomLeft,
child: Image.asset('assets/images/logo.png'), children: <Widget>[
//child: FlutterLogo(size: 120,), SizedBox(
height: 150,
child: Image.asset('assets/images/logo.png'),
),
Positioned(child: Text('онлайн касса', style: TextStyle(fontWeight: FontWeight.bold),), bottom: 23.0,left: 25.0,),
],
), ),
InputField( InputField(
placeholder: 'Электронная почта', placeholder: 'Электронная почта',
controller: emailController, controller: emailController,
@ -68,9 +80,15 @@ class LoginView extends StatelessWidget {
], ],
), ),
verticalSpaceLarge, verticalSpaceLarge,
TextLink( // TextLink(
'Регистрация', // 'Регистрация',
onPressed: () {}, // onPressed: () {},
// ),
IconButton(
icon: Icon(MdiIcons.qrcodeScan),
iconSize: 40,
tooltip: "Scan",
onPressed: scan,
) )
], ],
), ),
@ -78,5 +96,42 @@ class LoginView extends StatelessWidget {
}); });
} }
_pressBtnEnter() async {
Redux.store
.dispatch(authenticate(emailController.text, passwordController.text));
}
Future<void> scan() async {
try {
var options = ScanOptions(strings: {
"cancel": 'Отмена',
"flash_on": 'Вкл фонарик',
"flash_off": 'Выкл фонарик',
});
var result = await BarcodeScanner.scan(options: options);
print(result.type); // The result type (barcode, cancelled, failed)
print(result.rawContent); // The barcode content
print(result.format); // The barcode format (as enum)
print(result
.formatNote); // If a unknown format was scanned this field contains a note
if (result.type == ResultType.Barcode &&
result.rawContent?.length == 60) {
Redux.store.dispatch(authenticateToken(result.rawContent));
} else {
_dialogService.showDialog(description: 'Не верный формат QR кода');
}
} on PlatformException catch (e) {
var result = ScanResult.create();
result.type = ResultType.Error;
result.format = BarcodeFormat.unknown;
if (e.code == BarcodeScanner.cameraAccessDenied) {
result.rawContent = 'The user did not grant the camera permission!';
_dialogService.showDialog(
description: 'Нет доступа до камеры устройства');
} else {
result.rawContent = 'Unknown error: $e';
_dialogService.showDialog(description: 'Неизвестная ошибка: $e');
}
}
}
} }

View File

@ -6,6 +6,8 @@ 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/DataService.dart';
import 'package:aman_kassa_flutter/core/services/dialog_service.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/core/services/navigator_service.dart';
import 'package:aman_kassa_flutter/redux/actions/calc_actions.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/operation_const.dart';
import 'package:aman_kassa_flutter/redux/constants/setting_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/calc_state.dart';
@ -82,7 +84,7 @@ class _PaymentViewState extends State<PaymentView> {
if(widget.model.mode == SettingModeCalc) { if(widget.model.mode == SettingModeCalc) {
return StoreConnector<AppState, CalcState>( return StoreConnector<AppState, CalcState>(
converter: (store) => store.state.calcState, converter: (store) => store.state.calcState,
builder: (context, vm) { builder: (_, vm) {
return Text('${totalCalc(vm.calcItems)} тнг', style: TextStyle( return Text('${totalCalc(vm.calcItems)} тнг', style: TextStyle(
fontWeight: FontWeight.bold, fontWeight: FontWeight.bold,
color: Colors.black87, color: Colors.black87,
@ -92,7 +94,7 @@ class _PaymentViewState extends State<PaymentView> {
} }
return StoreConnector<AppState, KassaState>( return StoreConnector<AppState, KassaState>(
converter: (store) => store.state.kassaState, converter: (store) => store.state.kassaState,
builder: (context, vm) { builder: (_, vm) {
return Text('${totalKassa(vm.kassaItems)} тнг', style: TextStyle(fontWeight: FontWeight.bold, color: Colors.black87, fontSize: 35 )); return Text('${totalKassa(vm.kassaItems)} тнг', style: TextStyle(fontWeight: FontWeight.bold, color: Colors.black87, fontSize: 35 ));
} }
); );
@ -128,13 +130,24 @@ class _PaymentViewState extends State<PaymentView> {
AppState _state = Redux.store.state; AppState _state = Redux.store.state;
String _token = _state.userState.user.token; String _token = _state.userState.user.token;
String _tradeType = _state.settingState.tradeType; String _tradeType = _state.settingState.tradeType;
List<ProductDao> items = _state.kassaState.kassaItems; String _mode = _state.settingState.mode;
Response<dynamic> response = await _dataService.sellOrReturn(token: _token, items: items, paymentType: type, operationType: widget.model.operationType, tradeType: _tradeType ); if(_mode == SettingModeCalc){
_tradeType = SettingTradeTypeGood;
}
List<ProductDao> kassaItems = _state.kassaState.kassaItems;
List<CalcModel> calcItems = _state.calcState.calcItems;
Response<dynamic> response = await _dataService.sellOrReturn(token: _token, kassaItems: kassaItems, paymentType: type, operationType: widget.model.operationType, tradeType: _tradeType, calcItems: calcItems, mode: _mode );
Navigator.of(context, rootNavigator: true).pop(); Navigator.of(context, rootNavigator: true).pop();
setState(() { isBusy = false; }); setState(() { isBusy = false; });
if(response.operation){ if(response.operation){
String message = response.body['message']; String message = response.body['message'];
String check = response.body['check']; String check = response.body['check'];
// if(_mode == SettingModeCalc){
// Redux.store.dispatch(cleanCalcItems);
// } else if(_mode == SettingModeKassa) {
// Redux.store.dispatch(cleanKassaItems);
// }
_navigatorService.pop(); _navigatorService.pop();
_navigatorService.push(ImageShowRoute, arguments: ImageShowModel(check, message)); _navigatorService.push(ImageShowRoute, arguments: ImageShowModel(check, message));
} else if(!response.operation && response.status !=500) { } else if(!response.operation && response.status !=500) {

View File

@ -1,5 +1,6 @@
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/shared/ui_helpers.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
/// A button that shows a busy indicator in place of title /// A button that shows a busy indicator in place of title
@ -9,13 +10,15 @@ class BusyButton extends StatefulWidget {
final Function onPressed; final Function onPressed;
final bool enabled; final bool enabled;
final Color mainColor; final Color mainColor;
final IconData icon;
const BusyButton( const BusyButton(
{ {
@required this.title, @required this.title,
this.busy = false, this.busy = false,
@required this.onPressed, @required this.onPressed,
this.enabled = true, this.enabled = true,
this.mainColor this.mainColor,
this.icon
}); });
@override @override
@ -46,14 +49,20 @@ class _BusyButtonState extends State<BusyButton> {
margin: EdgeInsets.symmetric( margin: EdgeInsets.symmetric(
horizontal: widget.busy ? 10 : 25, horizontal: widget.busy ? 10 : 25,
vertical: widget.busy ? 10 : 15), vertical: widget.busy ? 10 : 15),
child: !widget.busy child: Row(
? Text( mainAxisAlignment: MainAxisAlignment.center,
widget.title, children: <Widget>[
style: buttonTitleTextStyle, widget.icon!=null ? Container(child: (Icon(widget.icon, color: whiteColor,)), margin: const EdgeInsets.only(right: 10.0 ),) : (Container()),
) !widget.busy
: CircularProgressIndicator( ? Text(
strokeWidth: 2, widget.title,
valueColor: AlwaysStoppedAnimation<Color>(Colors.white)), style: buttonTitleTextStyle,
)
: CircularProgressIndicator(
strokeWidth: 2,
valueColor: AlwaysStoppedAnimation<Color>(Colors.white)),
],
),
), ),
), ),
), ),

View File

@ -22,6 +22,13 @@ packages:
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "2.4.1" version: "2.4.1"
barcode_scan:
dependency: "direct main"
description:
name: barcode_scan
url: "https://pub.dartlang.org"
source: hosted
version: "3.0.1"
boolean_selector: boolean_selector:
dependency: transitive dependency: transitive
description: description:
@ -64,6 +71,13 @@ packages:
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "0.1.3" version: "0.1.3"
device_info:
dependency: "direct main"
description:
name: device_info
url: "https://pub.dartlang.org"
source: hosted
version: "0.4.2+4"
equatable: equatable:
dependency: "direct main" dependency: "direct main"
description: description:
@ -71,18 +85,25 @@ packages:
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "1.1.1" version: "1.1.1"
esys_flutter_share:
dependency: "direct main"
description:
name: esys_flutter_share
url: "https://pub.dartlang.org"
source: hosted
version: "1.0.2"
fixnum:
dependency: transitive
description:
name: fixnum
url: "https://pub.dartlang.org"
source: hosted
version: "0.10.11"
flutter: flutter:
dependency: "direct main" dependency: "direct main"
description: flutter description: flutter
source: sdk source: sdk
version: "0.0.0" version: "0.0.0"
flutter_boom_menu:
dependency: "direct main"
description:
name: flutter_boom_menu
url: "https://pub.dartlang.org"
source: hosted
version: "1.0.2"
flutter_redux: flutter_redux:
dependency: "direct main" dependency: "direct main"
description: description:
@ -95,6 +116,11 @@ packages:
description: flutter description: flutter
source: sdk source: sdk
version: "0.0.0" version: "0.0.0"
flutter_web_plugins:
dependency: transitive
description: flutter
source: sdk
version: "0.0.0"
get_it: get_it:
dependency: "direct main" dependency: "direct main"
description: description:
@ -172,13 +198,6 @@ packages:
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "0.0.4" version: "0.0.4"
observable_ish:
dependency: transitive
description:
name: observable_ish
url: "https://pub.dartlang.org"
source: hosted
version: "2.1.4"
path: path:
dependency: transitive dependency: transitive
description: description:
@ -235,6 +254,13 @@ packages:
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "1.0.2" version: "1.0.2"
protobuf:
dependency: transitive
description:
name: protobuf
url: "https://pub.dartlang.org"
source: hosted
version: "1.0.1"
provider: provider:
dependency: "direct main" dependency: "direct main"
description: description:
@ -242,13 +268,6 @@ packages:
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "4.1.2" version: "4.1.2"
provider_architecture:
dependency: "direct main"
description:
name: provider_architecture
url: "https://pub.dartlang.org"
source: hosted
version: "1.1.1+1"
quiver: quiver:
dependency: transitive dependency: transitive
description: description:
@ -263,6 +282,20 @@ packages:
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "4.0.0" version: "4.0.0"
redux_persist:
dependency: "direct main"
description:
name: redux_persist
url: "https://pub.dartlang.org"
source: hosted
version: "0.8.4"
redux_persist_flutter:
dependency: "direct main"
description:
name: redux_persist_flutter
url: "https://pub.dartlang.org"
source: hosted
version: "0.8.2"
redux_thunk: redux_thunk:
dependency: "direct main" dependency: "direct main"
description: description:
@ -277,18 +310,39 @@ packages:
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "0.1.9" version: "0.1.9"
shared_preferences:
dependency: transitive
description:
name: shared_preferences
url: "https://pub.dartlang.org"
source: hosted
version: "0.5.7+3"
shared_preferences_macos:
dependency: transitive
description:
name: shared_preferences_macos
url: "https://pub.dartlang.org"
source: hosted
version: "0.0.1+10"
shared_preferences_platform_interface:
dependency: transitive
description:
name: shared_preferences_platform_interface
url: "https://pub.dartlang.org"
source: hosted
version: "1.0.4"
shared_preferences_web:
dependency: transitive
description:
name: shared_preferences_web
url: "https://pub.dartlang.org"
source: hosted
version: "0.1.2+7"
sky_engine: sky_engine:
dependency: transitive dependency: transitive
description: flutter description: flutter
source: sdk source: sdk
version: "0.0.99" version: "0.0.99"
sliding_up_panel:
dependency: "direct main"
description:
name: sliding_up_panel
url: "https://pub.dartlang.org"
source: hosted
version: "1.0.2"
source_span: source_span:
dependency: transitive dependency: transitive
description: description:
@ -317,13 +371,6 @@ packages:
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "1.9.3" version: "1.9.3"
stacked:
dependency: "direct main"
description:
name: stacked
url: "https://pub.dartlang.org"
source: hosted
version: "1.5.2"
stream_channel: stream_channel:
dependency: transitive dependency: transitive
description: description:

View File

@ -10,8 +10,8 @@ dependencies:
redux: ^4.0.0 redux: ^4.0.0
flutter_redux: ^0.6.0 flutter_redux: ^0.6.0
redux_thunk: ^0.3.0 redux_thunk: ^0.3.0
stacked : ^1.5.2 redux_persist: ^0.8.4
provider_architecture: ^1.0.3 redux_persist_flutter: ^0.8.2
responsive_builder: ^0.1.4 responsive_builder: ^0.1.4
provider: ^4.1.2 provider: ^4.1.2
logger: ^0.9.1 logger: ^0.9.1
@ -21,10 +21,11 @@ dependencies:
sqflite: ^1.3.0 sqflite: ^1.3.0
path_provider: ^1.6.9 path_provider: ^1.6.9
google_fonts: ^1.1.0 google_fonts: ^1.1.0
flutter_boom_menu: ^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 intl: ^0.16.1
barcode_scan: ^3.0.1
device_info: ^0.4.2+4
esys_flutter_share: ^1.0.2
dev_dependencies: dev_dependencies:
flutter_test: flutter_test:
sdk: flutter sdk: flutter