redux main state/main_state.dart
parent
71fb01ee93
commit
1d18e70208
|
|
@ -0,0 +1,33 @@
|
|||
import 'package:sqflite/sqflite.dart';
|
||||
|
||||
const String Category_tableName = 'goods_category';
|
||||
const String Category_columnId = 'id';
|
||||
const String Category_columnParentIn = 'parent_id';
|
||||
const String Category_columnName = 'name';
|
||||
|
||||
class Category {
|
||||
int id;
|
||||
int parentIn;
|
||||
String name;
|
||||
|
||||
Map<String, dynamic> toMap() {
|
||||
var map = <String, dynamic>{
|
||||
Category_columnParentIn: parentIn,
|
||||
Category_columnName: name,
|
||||
};
|
||||
if (id != null) {
|
||||
map[Category_columnId] = id;
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
Category();
|
||||
|
||||
Category.fromMap(Map<String, dynamic> map) {
|
||||
id = map[Category_columnId];
|
||||
parentIn = map[Category_columnParentIn];
|
||||
name = map[Category_columnName];
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,45 @@
|
|||
import 'package:sqflite/sqflite.dart';
|
||||
|
||||
const String Goog_tableName = 'goods';
|
||||
const String Goog_columnId = 'id';
|
||||
const String Goog_columnArticul = 'articul';
|
||||
const String Goog_columnName = 'name';
|
||||
const String Goog_columnPrice = 'price';
|
||||
const String Goog_columnCategoryId = 'category_id';
|
||||
const String Goog_columnEan = 'ean';
|
||||
|
||||
class Good {
|
||||
int id;
|
||||
int articul;
|
||||
String name;
|
||||
double price;
|
||||
int categoryId;
|
||||
String ean;
|
||||
|
||||
Map<String, dynamic> toMap() {
|
||||
var map = <String, dynamic>{
|
||||
Goog_columnArticul: articul,
|
||||
Goog_columnName: name,
|
||||
Goog_columnPrice: price,
|
||||
Goog_columnCategoryId: categoryId,
|
||||
Goog_columnEan: ean,
|
||||
};
|
||||
if (id != null) {
|
||||
map[Goog_columnId] = id;
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
Good();
|
||||
|
||||
Good.fromMap(Map<String, dynamic> map) {
|
||||
id = map[Goog_columnId];
|
||||
articul = map[Goog_columnArticul];
|
||||
name = map[Goog_columnName];
|
||||
price = map[Goog_columnPrice]?.toDouble();
|
||||
categoryId = map[Goog_columnCategoryId];
|
||||
ean = map[Goog_columnEan];
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,39 @@
|
|||
import 'package:sqflite/sqflite.dart';
|
||||
|
||||
const String Service_tableName = 'services';
|
||||
const String Service_columnId = 'id';
|
||||
const String Service_columnArticul = 'articul';
|
||||
const String Service_columnName = 'name';
|
||||
const String Service_columnPrice = 'price';
|
||||
const String Service_columnCategoryId = 'category_id';
|
||||
const String Service_columnEan = 'ean';
|
||||
|
||||
class Service {
|
||||
int id;
|
||||
int articul;
|
||||
String name;
|
||||
double price;
|
||||
|
||||
Map<String, dynamic> toMap() {
|
||||
var map = <String, dynamic>{
|
||||
Service_columnArticul: articul,
|
||||
Service_columnName: name,
|
||||
Service_columnPrice: price,
|
||||
};
|
||||
if (id != null) {
|
||||
map[Service_columnId] = id;
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
Service();
|
||||
|
||||
Service.fromMap(Map<String, dynamic> map) {
|
||||
id = map[Service_columnId];
|
||||
articul = map[Service_columnArticul];
|
||||
name = map[Service_columnName];
|
||||
price = map[Service_columnPrice]?.toDouble();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -1,5 +1,9 @@
|
|||
|
||||
|
||||
import 'package:aman_kassa_flutter/core/services/DataService.dart';
|
||||
|
||||
import '../core/services/DbService.dart';
|
||||
|
||||
import '../core/services/ApiService.dart';
|
||||
import '../core/services/dialog_service.dart';
|
||||
import '../core/logger.dart';
|
||||
|
|
@ -19,6 +23,14 @@ class LocatorInjector {
|
|||
locator.registerLazySingleton<NavigatorService>(() => NavigatorService());
|
||||
_log.d('Initializing Dialog Service');
|
||||
locator.registerLazySingleton<DialogService>(() => DialogService());
|
||||
_log.d('Initializing DbService Service');
|
||||
locator.registerLazySingleton<DbService>(() => DbService.instance);
|
||||
|
||||
|
||||
// depencies
|
||||
|
||||
|
||||
_log.d('Initializing DataService Service');
|
||||
locator.registerLazySingleton<DataService>(() => DataService());
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
import 'package:flutter/material.dart';
|
||||
|
||||
class Choice {
|
||||
const Choice({this.title, this.icon, this.command});
|
||||
final String command;
|
||||
final String title;
|
||||
final IconData icon;
|
||||
}
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
class DictDao {
|
||||
final int id;
|
||||
final String name;
|
||||
DictDao({ this.id, this.name});
|
||||
}
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
class Message {
|
||||
final String message;
|
||||
|
||||
Message({this.message});
|
||||
|
||||
|
||||
static Message fromJson(Map<String, dynamic> data) => Message(message : data['message']);
|
||||
}
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
class ProductDao {
|
||||
final String name;
|
||||
final double price;
|
||||
int count;
|
||||
final num price;
|
||||
num count;
|
||||
|
||||
|
||||
ProductDao( {this.name, this.price, this.count});
|
||||
|
|
|
|||
|
|
@ -0,0 +1,20 @@
|
|||
class Response<T> {
|
||||
final T body;
|
||||
final int status;
|
||||
final bool operation;
|
||||
|
||||
Response({this.body, this.operation, this.status});
|
||||
|
||||
factory Response.fromJson(Map<String, dynamic> data, Function parser) {
|
||||
return Response(
|
||||
body: parser(data['body']),
|
||||
status: data['status'],
|
||||
operation: data['operation']);
|
||||
}
|
||||
factory Response.fromJsonDynamic(Map<String, dynamic> data) {
|
||||
return Response(
|
||||
body: data['body'],
|
||||
status: data['status'],
|
||||
operation: data['operation']);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,16 +0,0 @@
|
|||
class Session {
|
||||
String token;
|
||||
int appCompanyId;
|
||||
int kassaId;
|
||||
int userId;
|
||||
String message;
|
||||
Session();
|
||||
|
||||
|
||||
Session.fromData(String token ,Map<String, dynamic> data)
|
||||
: token = token,
|
||||
appCompanyId = data['app_company_id'],
|
||||
userId = data['user_id'],
|
||||
message = data['message'],
|
||||
kassaId = data['kassa_id'];
|
||||
}
|
||||
|
|
@ -1,3 +1,5 @@
|
|||
import 'package:aman_kassa_flutter/core/services/DataService.dart';
|
||||
import 'package:aman_kassa_flutter/core/services/DbService.dart';
|
||||
import 'package:provider/single_child_widget.dart';
|
||||
|
||||
import '../core/locator.dart';
|
||||
|
|
@ -15,15 +17,20 @@ class ProviderInjector {
|
|||
];
|
||||
|
||||
static List<SingleChildWidget> _independentServices = [
|
||||
Provider.value(value: locator<NavigatorService>()),
|
||||
Provider.value(value: locator<ApiService>()),
|
||||
// Provider.value(value: locator<NavigatorService>()),
|
||||
// Provider.value(value: locator<ApiService>()),
|
||||
// Provider.value(value: locator<DbService>()),
|
||||
];
|
||||
|
||||
static List<SingleChildWidget> _dependentServices = [
|
||||
ProxyProvider<ApiService, AuthenticationService>(
|
||||
update: (context, api, authenticationService) =>
|
||||
AuthenticationService(api: api),
|
||||
)
|
||||
// ProxyProvider<ApiService, AuthenticationService>(
|
||||
// update: (context, api, authenticationService) =>
|
||||
// AuthenticationService(api: api),
|
||||
// ),
|
||||
// ProxyProvider2< ApiService ,DbService, DataService>(
|
||||
// update: (context,api , db, authenticationService) =>
|
||||
// DataService(api: api, db: db),
|
||||
// )
|
||||
];
|
||||
|
||||
static List<SingleChildWidget> _consumableServices = [];
|
||||
|
|
|
|||
|
|
@ -2,10 +2,11 @@ import 'dart:convert';
|
|||
import 'dart:io';
|
||||
|
||||
import 'package:aman_kassa_flutter/core/base/base_service.dart';
|
||||
import 'package:aman_kassa_flutter/core/models/session.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/Response.dart';
|
||||
import '../models/authResponse.dart';
|
||||
|
||||
|
||||
import 'package:http/http.dart' as http;
|
||||
|
||||
/// The service responsible for networking requests
|
||||
|
|
@ -21,20 +22,25 @@ class ApiService extends BaseService {
|
|||
};
|
||||
var response = await requestFormData('/authenticate', requestBody);
|
||||
final respStr = await response.stream.bytesToString();
|
||||
print(respStr);
|
||||
AuthResponse aman = AuthResponse.fromJson(json.decode(respStr));
|
||||
return aman.body;
|
||||
}
|
||||
|
||||
Future<Session> isActive(String token) async {
|
||||
Future<Response<Message>> isActive(String token) async {
|
||||
Map<String, String> requestBody = <String, String>{'api_token': token};
|
||||
var response = await requestFormData('/test_auth', requestBody);
|
||||
final respStr = await response.stream.bytesToString();
|
||||
return Session.fromData(token, json.decode(respStr)['body']);
|
||||
return Response.fromJson(json.decode(respStr), Message.fromJson);
|
||||
}
|
||||
|
||||
Future<http.StreamedResponse> requestFormData(
|
||||
String point, Map<String, String> requestBody) async {
|
||||
Future<Response<Message>> logout(String token) async {
|
||||
Map<String, String> requestBody = <String, String>{'api_token': token};
|
||||
var response = await requestFormData('/logout', requestBody);
|
||||
final respStr = await response.stream.bytesToString();
|
||||
return Response.fromJson(json.decode(respStr), Message.fromJson);
|
||||
}
|
||||
|
||||
Future<http.StreamedResponse> requestFormData(String point, Map<String, String> requestBody) async {
|
||||
Map<String, String> headers = <String, String>{
|
||||
HttpHeaders.contentTypeHeader: "multipart/form-data",
|
||||
HttpHeaders.cacheControlHeader: "no-cache"
|
||||
|
|
@ -48,4 +54,26 @@ class ApiService extends BaseService {
|
|||
return await request.send();
|
||||
}
|
||||
|
||||
Future<Response<dynamic>> getGoodsFromServer(String token) async {
|
||||
Map<String, String> requestBody = <String, String>{'api_token': token};
|
||||
var response = await requestFormData('/goods', requestBody);
|
||||
final respStr = await response.stream.bytesToString();
|
||||
print(respStr);
|
||||
return Response.fromJsonDynamic(json.decode(respStr));
|
||||
}
|
||||
|
||||
Future<Response<dynamic>> getCategoryFromServer(String token) async {
|
||||
Map<String, String> requestBody = <String, String>{'api_token': token};
|
||||
var response = await requestFormData('/goods_category', requestBody);
|
||||
final respStr = await response.stream.bytesToString();
|
||||
print(respStr);
|
||||
return Response.fromJsonDynamic(json.decode(respStr));
|
||||
}
|
||||
Future<Response<dynamic>> getServiceFromServer(String token) async {
|
||||
Map<String, String> requestBody = <String, String>{'api_token': token};
|
||||
var response = await requestFormData('/services', requestBody);
|
||||
final respStr = await response.stream.bytesToString();
|
||||
print(respStr);
|
||||
return Response.fromJsonDynamic(json.decode(respStr));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,64 @@
|
|||
import 'dart:convert';
|
||||
|
||||
import 'package:aman_kassa_flutter/core/base/base_service.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/Service.dart';
|
||||
import 'package:aman_kassa_flutter/core/locator.dart';
|
||||
import 'package:aman_kassa_flutter/core/models/Response.dart';
|
||||
import 'package:aman_kassa_flutter/core/services/DbService.dart';
|
||||
|
||||
import 'ApiService.dart';
|
||||
|
||||
class DataService extends BaseService {
|
||||
final ApiService _api = locator<ApiService>();
|
||||
final DbService _db = locator<DbService>();
|
||||
|
||||
Future<List<Category>> getCategoriesByParentId ( {int parentId} ) async {
|
||||
List<Map<String, dynamic>> list = await _db.queryRowsWithWhere(Category_tableName, '$Category_columnParentIn = ?', [parentId ?? 0 ]);
|
||||
return list.map((e) => Category.fromMap(e)).toList();
|
||||
}
|
||||
|
||||
Future<List<Good>> getGoodsByCategoryId ( {int categoryId} ) async {
|
||||
List<Map<String, dynamic>> list = await _db.queryRowsWithWhere(Goog_tableName, '$Goog_columnCategoryId = ?', [categoryId ?? 0]);
|
||||
return list.map((e) => Good.fromMap(e)).toList();
|
||||
}
|
||||
|
||||
Future<bool> getDataFromServer(String token) async {
|
||||
try {
|
||||
|
||||
Response<dynamic> goods = await _api.getGoodsFromServer(token);
|
||||
Response<dynamic> categories = await _api.getCategoryFromServer(token);
|
||||
Response<dynamic> services = await _api.getServiceFromServer(token);
|
||||
await _db.deleteAll(Goog_tableName);
|
||||
await _db.deleteAll(Category_tableName);
|
||||
await _db.deleteAll(Service_tableName);
|
||||
log.i('All tables cleaned');
|
||||
for (var key in goods.body.keys) {
|
||||
print(goods.body[key]);
|
||||
Good row = Good.fromMap(goods.body[key]);
|
||||
_db.insert(Goog_tableName,row.toMap());
|
||||
}
|
||||
log.i('Inserted ${goods.body.length} to table $Goog_tableName');
|
||||
|
||||
for (var el in categories.body) {
|
||||
print(el);
|
||||
Category row = Category.fromMap(el);
|
||||
_db.insert(Category_tableName,row.toMap());
|
||||
}
|
||||
log.i('Inserted ${categories.body.length} to table $Category_tableName');
|
||||
|
||||
for (var key in services.body.keys) {
|
||||
print(services.body[key]);
|
||||
Service row = Service.fromMap(services.body[key]);
|
||||
_db.insert(Service_tableName,row.toMap());
|
||||
}
|
||||
log.i('Inserted ${services.body.length} to table $Service_tableName');
|
||||
|
||||
return true;
|
||||
} catch (e) {
|
||||
print(e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,129 @@
|
|||
import 'dart:io';
|
||||
|
||||
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/Category.dart';
|
||||
import 'package:aman_kassa_flutter/core/entity/Service.dart';
|
||||
import 'package:sqflite/sqflite.dart';
|
||||
import 'package:path/path.dart';
|
||||
import 'package:path_provider/path_provider.dart';
|
||||
|
||||
class DbService extends BaseService {
|
||||
static final _databaseName = "AmanFlutterDb.db";
|
||||
static final _databaseVersion = 5;
|
||||
|
||||
// make this a singleton class
|
||||
DbService._privateConstructor();
|
||||
|
||||
static final DbService instance = DbService._privateConstructor();
|
||||
|
||||
// only have a single app-wide reference to the database
|
||||
static Database _database;
|
||||
|
||||
Future<Database> get database async {
|
||||
if (_database != null) return _database;
|
||||
// lazily instantiate the db the first time it is accessed
|
||||
_database = await _initDatabase();
|
||||
return _database;
|
||||
}
|
||||
|
||||
// this opens the database (and creates it if it doesn't exist)
|
||||
_initDatabase() async {
|
||||
Directory documentsDirectory = await getApplicationDocumentsDirectory();
|
||||
String path = join(documentsDirectory.path, _databaseName);
|
||||
print(path);
|
||||
return await openDatabase(path,
|
||||
version: _databaseVersion,
|
||||
onUpgrade: _onUpdate,
|
||||
onCreate: _onCreate
|
||||
);
|
||||
}
|
||||
Future _onUpdate(Database db, int oldVersion, int newVersion) async {
|
||||
print('update from $oldVersion to $newVersion');
|
||||
//Goods table
|
||||
await db.execute('''
|
||||
DROP TABLE IF EXISTS $Goog_tableName;
|
||||
DROP TABLE IF EXISTS $Category_tableName;
|
||||
DROP TABLE IF EXISTS $Service_tableName;
|
||||
''');
|
||||
_onCreate(db, newVersion);
|
||||
}
|
||||
|
||||
Future _onCreate(Database db, int version) async {
|
||||
print('create tables');
|
||||
//Goods table
|
||||
await db.execute('''
|
||||
CREATE TABLE IF NOT EXISTS $Goog_tableName (
|
||||
$Goog_columnId integer primary key unique,
|
||||
$Goog_columnArticul integer not null,
|
||||
$Goog_columnName text not null,
|
||||
$Goog_columnPrice real not null,
|
||||
$Goog_columnCategoryId integer not null,
|
||||
$Goog_columnEan text);
|
||||
''');
|
||||
await db.execute('''
|
||||
CREATE TABLE IF NOT EXISTS $Category_tableName (
|
||||
$Category_columnId integer primary key unique,
|
||||
$Category_columnName text not null,
|
||||
$Category_columnParentIn integer);
|
||||
''');
|
||||
await db.execute('''
|
||||
CREATE TABLE IF NOT EXISTS $Service_tableName (
|
||||
$Service_columnId integer primary key unique,
|
||||
$Service_columnArticul integer not null,
|
||||
$Service_columnName text not null,
|
||||
$Service_columnPrice real not null);
|
||||
''');
|
||||
|
||||
}
|
||||
|
||||
// Inserts a row in the database where each key in the Map is a column name
|
||||
// and the value is the column value. The return value is the id of the
|
||||
// inserted row.
|
||||
Future<int> insert(String table, Map<String, dynamic> row) async {
|
||||
Database db = await instance.database;
|
||||
return await db.insert(table, row);
|
||||
}
|
||||
|
||||
// All of the rows are returned as a list of maps, where each map is
|
||||
// a key-value list of columns.
|
||||
Future<List<Map<String, dynamic>>> queryAllRows(String table) async {
|
||||
Database db = await instance.database;
|
||||
return await db.query(table);
|
||||
}
|
||||
|
||||
Future<List<Map<String, dynamic>>> queryRowsWithWhere(String table, String where, List<dynamic> args ) async {
|
||||
Database db = await instance.database;
|
||||
return await db.query(table, where: where, whereArgs: args );
|
||||
}
|
||||
|
||||
// All of the methods (insert, query, update, delete) can also be done using
|
||||
// raw SQL commands. This method uses a raw query to give the row count.
|
||||
Future<int> queryRowCount(String table) async {
|
||||
Database db = await instance.database;
|
||||
return Sqflite.firstIntValue(
|
||||
await db.rawQuery('SELECT COUNT(*) FROM $table'));
|
||||
}
|
||||
|
||||
// We are assuming here that the id column in the map is set. The other
|
||||
// column values will be used to update the row.
|
||||
Future<int> update(String table, Map<String, dynamic> row) async {
|
||||
Database db = await instance.database;
|
||||
int id = row['id'];
|
||||
return await db.update(table, row, where: 'id = ?', whereArgs: [id]);
|
||||
}
|
||||
|
||||
// Deletes the row specified by the id. The number of affected rows is
|
||||
// returned. This should be 1 as long as the row exists.
|
||||
Future<int> delete(String table, int id) async {
|
||||
Database db = await instance.database;
|
||||
return await db.delete(table, where: 'id = ?', whereArgs: [id]);
|
||||
}
|
||||
|
||||
Future<int> deleteAll(String table) async {
|
||||
Database db = await instance.database;
|
||||
return await db.delete(table);
|
||||
}
|
||||
|
||||
Future close() async => instance.close();
|
||||
}
|
||||
|
|
@ -1,5 +1,6 @@
|
|||
import 'package:aman_kassa_flutter/core/base/base_service.dart';
|
||||
import 'package:aman_kassa_flutter/core/models/session.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/user.dart';
|
||||
import 'package:aman_kassa_flutter/core/models/authResponse.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
|
|
@ -14,9 +15,6 @@ class AuthenticationService extends BaseService {
|
|||
User _currentUser;
|
||||
User get currentUser => _currentUser;
|
||||
|
||||
Session _session;
|
||||
Session get currentSession => _session;
|
||||
|
||||
Future<AuthBody> loginWithEmail({
|
||||
@required String email,
|
||||
@required String password,
|
||||
|
|
@ -34,9 +32,18 @@ class AuthenticationService extends BaseService {
|
|||
}
|
||||
|
||||
Future<bool> isUserLoggedIn(String token) async {
|
||||
Session session = await _api.isActive(token);
|
||||
if ("OK" == session.message) {
|
||||
_session = session;
|
||||
Response<Message> session = await _api.isActive(token);
|
||||
if ("OK" == session.body.message) {
|
||||
//_session = session;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
Future<bool> logout(String token) async {
|
||||
Response<Message> session = await _api.logout(token);
|
||||
if ("logout" == session.body.message) {
|
||||
//_session = session;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
|
|
|||
|
|
@ -1,9 +1,13 @@
|
|||
//general
|
||||
import 'package:flutter_redux/flutter_redux.dart';
|
||||
|
||||
import 'package:aman_kassa_flutter/shared/app_colors.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:google_fonts/google_fonts.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
//service & tools
|
||||
import 'package:redux/redux.dart';
|
||||
import 'package:aman_kassa_flutter/redux/store.dart';
|
||||
import 'core/locator.dart';
|
||||
import 'core/providers.dart';
|
||||
import 'core/router.dart';
|
||||
|
|
@ -19,14 +23,17 @@ void main() async {
|
|||
WidgetsFlutterBinding.ensureInitialized();
|
||||
//initialize locator
|
||||
await LocatorInjector.setupLocator();
|
||||
|
||||
await Redux.init();
|
||||
runApp(MainApplication());
|
||||
}
|
||||
|
||||
class MainApplication extends StatelessWidget {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return MultiProvider(
|
||||
providers: ProviderInjector.providers.toList(),
|
||||
return StoreProvider<AppState>(
|
||||
store: Redux.store,
|
||||
child: MaterialApp(
|
||||
theme: ThemeData(
|
||||
backgroundColor: backgroundColor,
|
||||
|
|
|
|||
|
|
@ -0,0 +1,71 @@
|
|||
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/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> 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)));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
@ -0,0 +1,72 @@
|
|||
import 'dart:convert';
|
||||
|
||||
import 'package:aman_kassa_flutter/core/locator.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/Response.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/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/state/user_state.dart';
|
||||
import 'package:redux/redux.dart';
|
||||
import 'package:meta/meta.dart';
|
||||
import 'package:redux_thunk/redux_thunk.dart';
|
||||
import '../store.dart';
|
||||
|
||||
@immutable
|
||||
class SetUserStateAction {
|
||||
final UserState userState;
|
||||
SetUserStateAction(this.userState);
|
||||
}
|
||||
final ApiService _api = locator<ApiService>();
|
||||
final NavigatorService _navigation = locator<NavigatorService>();
|
||||
final DialogService _dialogService = locator<DialogService>();
|
||||
|
||||
Future<void> checkUserAction(Store<AppState> store) async {
|
||||
store.dispatch(SetUserStateAction(UserState(isLoading: true)));
|
||||
try {
|
||||
Response<Message> session = await _api.isActive('test');
|
||||
bool isAuthenticated = "OK" == session.body.message;
|
||||
store.dispatch(
|
||||
SetUserStateAction(
|
||||
UserState(
|
||||
isLoading: false,
|
||||
isAuthenticated: isAuthenticated,
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
if(!isAuthenticated){
|
||||
_navigation.replace(LoginViewRoute);
|
||||
}
|
||||
|
||||
|
||||
} catch (error) {
|
||||
store.dispatch(SetUserStateAction(UserState(isLoading: false)));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
ThunkAction<AppState> authenticate(String email, String password) {
|
||||
return (Store<AppState> store) async {
|
||||
store.dispatch(SetUserStateAction(UserState(isLoading: true)));
|
||||
try {
|
||||
AuthBody result = await _api.authenticate(email, password);
|
||||
store.dispatch(SetUserStateAction(UserState(
|
||||
isLoading: false,
|
||||
loginFormMessage: LoginFormMessage(email: result.email?.join(","), password: result.password?.join(","), message: result.message),
|
||||
user: result.user
|
||||
)));
|
||||
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) {
|
||||
store.dispatch(SetUserStateAction(UserState(isLoading: false)));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
import 'package:aman_kassa_flutter/redux/actions/main_actions.dart';
|
||||
import 'package:aman_kassa_flutter/redux/state/main_state.dart';
|
||||
|
||||
mainReducer(MainState prevState, SetMainStateAction action) {
|
||||
final payload = action.mainState;
|
||||
return prevState.copyWith(
|
||||
bottomSheetElements: payload.bottomSheetElements,
|
||||
bottomSheetLoading: payload.bottomSheetLoading,
|
||||
prevCategories: payload.prevCategories,
|
||||
);
|
||||
}
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
import 'package:aman_kassa_flutter/redux/actions/user_actions.dart';
|
||||
import 'package:aman_kassa_flutter/redux/state/user_state.dart';
|
||||
|
||||
|
||||
userReducer(UserState prevState, SetUserStateAction action) {
|
||||
final payload = action.userState;
|
||||
return prevState.copyWith(
|
||||
isError: payload.isError,
|
||||
isLoading: payload.isLoading,
|
||||
user: payload.user,
|
||||
isAuthenticated: payload.isAuthenticated,
|
||||
loginFormMessage: payload.loginFormMessage,
|
||||
);
|
||||
}
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
import 'package:aman_kassa_flutter/core/models/DictDao.dart';
|
||||
import 'package:aman_kassa_flutter/core/models/user.dart';
|
||||
import 'package:meta/meta.dart';
|
||||
|
||||
@immutable
|
||||
class MainState {
|
||||
final List bottomSheetElements;
|
||||
final bool bottomSheetLoading;
|
||||
final List<DictDao> prevCategories;
|
||||
|
||||
MainState({this.bottomSheetElements, this.bottomSheetLoading, this.prevCategories});
|
||||
|
||||
factory MainState.initial() => MainState(
|
||||
bottomSheetElements: [],
|
||||
bottomSheetLoading: false,
|
||||
prevCategories: [],
|
||||
);
|
||||
|
||||
MainState copyWith({
|
||||
@required bottomSheetElements,
|
||||
@required bottomSheetLoading,
|
||||
@required prevCategories,
|
||||
}) {
|
||||
return MainState(
|
||||
bottomSheetElements: bottomSheetElements ?? this.bottomSheetElements,
|
||||
bottomSheetLoading: bottomSheetLoading ?? this.bottomSheetLoading,
|
||||
prevCategories: prevCategories ?? this.prevCategories,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,49 @@
|
|||
import 'package:aman_kassa_flutter/core/models/user.dart';
|
||||
import 'package:meta/meta.dart';
|
||||
|
||||
@immutable
|
||||
class UserState {
|
||||
final bool isError;
|
||||
final bool isLoading;
|
||||
final bool isAuthenticated;
|
||||
final LoginFormMessage loginFormMessage;
|
||||
final User user;
|
||||
|
||||
UserState({
|
||||
this.isError,
|
||||
this.isLoading,
|
||||
this.isAuthenticated,
|
||||
this.user,
|
||||
this.loginFormMessage
|
||||
});
|
||||
|
||||
factory UserState.initial() => UserState(
|
||||
isLoading: false,
|
||||
isError: false,
|
||||
isAuthenticated: false,
|
||||
loginFormMessage: LoginFormMessage(),
|
||||
);
|
||||
|
||||
UserState copyWith({
|
||||
@required bool isError,
|
||||
@required bool isLoading,
|
||||
@required User user,
|
||||
@required bool isAuthenticated,
|
||||
@required LoginFormMessage loginFormMessage,
|
||||
}) {
|
||||
return UserState(
|
||||
isError: isError ?? this.isError,
|
||||
isLoading: isLoading ?? this.isLoading,
|
||||
isAuthenticated: isAuthenticated ?? this.isAuthenticated,
|
||||
user: user ?? this.user,
|
||||
loginFormMessage: loginFormMessage ?? this.loginFormMessage,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class LoginFormMessage {
|
||||
final String email;
|
||||
final String password;
|
||||
final String message;
|
||||
LoginFormMessage({this.email, this.password, this.message});
|
||||
}
|
||||
|
|
@ -0,0 +1,69 @@
|
|||
import 'package:aman_kassa_flutter/redux/actions/main_actions.dart';
|
||||
import 'package:aman_kassa_flutter/redux/actions/user_actions.dart';
|
||||
import 'package:aman_kassa_flutter/redux/reducers/main_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/user_state.dart';
|
||||
import 'package:meta/meta.dart';
|
||||
import 'package:redux/redux.dart';
|
||||
import 'package:redux_thunk/redux_thunk.dart';
|
||||
|
||||
|
||||
//reducer context
|
||||
AppState appReducer(AppState state, dynamic action) {
|
||||
|
||||
if (action is SetUserStateAction) { /** UserAction **/
|
||||
final nextUserState = userReducer(state.userState, action);
|
||||
return state.copyWith(userState: nextUserState);
|
||||
} else if(action is SetMainStateAction) { /** MainAction **/
|
||||
final nextMainState = mainReducer(state.mainState, action);
|
||||
return state.copyWith(mainState: nextMainState);
|
||||
}
|
||||
return state;
|
||||
}
|
||||
|
||||
//Main State
|
||||
@immutable
|
||||
class AppState {
|
||||
final UserState userState;
|
||||
final MainState mainState;
|
||||
AppState({
|
||||
@required this.userState,
|
||||
@required this.mainState,
|
||||
});
|
||||
|
||||
//stable work
|
||||
AppState copyWith({
|
||||
UserState userState,
|
||||
MainState mainState,
|
||||
}) {
|
||||
return AppState(
|
||||
userState: userState ?? this.userState,
|
||||
mainState: mainState ?? this.mainState,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class Redux {
|
||||
static Store<AppState> _store;
|
||||
|
||||
static Store<AppState> get store {
|
||||
if (_store == null) {
|
||||
throw Exception("store is not initialized");
|
||||
} else {
|
||||
return _store;
|
||||
}
|
||||
}
|
||||
|
||||
//initial context
|
||||
static Future<void> init() async {
|
||||
final userStateInitial = UserState.initial();
|
||||
final mainStateInitial = MainState.initial();
|
||||
|
||||
_store = Store<AppState>(
|
||||
appReducer,
|
||||
middleware: [thunkMiddleware],
|
||||
initialState: AppState(userState: userStateInitial, mainState: mainStateInitial),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -20,8 +20,8 @@ const EdgeInsets largeFieldPadding =
|
|||
const EdgeInsets.symmetric(horizontal: 15, vertical: 15);
|
||||
|
||||
// Text Variables
|
||||
const TextStyle productTextStyle = const TextStyle(fontWeight: FontWeight.w400, color: Colors.black, fontSize: 15);
|
||||
const TextStyle buttonTitleTextStyle = const TextStyle(fontWeight: FontWeight.w400, color: whiteColor, fontSize: 15);
|
||||
|
||||
const TextStyle buttonBigTitleTextStyle = const TextStyle(fontWeight: FontWeight.w400, color: whiteColor, fontSize: 22, );
|
||||
|
||||
const TextStyle stepTitleTextStyle =
|
||||
|
|
|
|||
|
|
@ -1,50 +1,57 @@
|
|||
library home_view;
|
||||
|
||||
import 'package:aman_kassa_flutter/core/locator.dart';
|
||||
import 'package:aman_kassa_flutter/core/models/Choice.dart';
|
||||
import 'package:aman_kassa_flutter/core/services/DataService.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:flutter/material.dart';
|
||||
import 'package:google_fonts/google_fonts.dart';
|
||||
import 'package:material_design_icons_flutter/material_design_icons_flutter.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:stacked/stacked.dart';
|
||||
import 'package:aman_kassa_flutter/core/models/ProductDao.dart';
|
||||
import 'package:aman_kassa_flutter/widgets/components/ProductListItem.dart';
|
||||
import 'home_view_model.dart';
|
||||
import '../../widgets/components/calculator/calculator-buttons.dart';
|
||||
import '../../widgets/components/calculator/number-display.dart';
|
||||
|
||||
part './tabs/KassaTab.dart';
|
||||
part './tabs/CalculatorTab.dart';
|
||||
part './tabs/AdditionalTab.dart';
|
||||
import './tabs/KassaTab.dart';
|
||||
import './tabs/AdditionalTab.dart';
|
||||
import './tabs/CalculatorTab.dart';
|
||||
|
||||
class Choice {
|
||||
const Choice({this.title, this.icon});
|
||||
|
||||
final String title;
|
||||
final IconData icon;
|
||||
}
|
||||
|
||||
const List<Choice> choices = const <Choice>[
|
||||
const Choice(title: 'Обновить номенклатуру', icon: Icons.directions_car),
|
||||
const Choice(title: 'Помощь', icon: Icons.directions_car),
|
||||
const Choice(title: 'О Программе', icon: Icons.directions_car),
|
||||
const Choice(title: 'Язык', icon: Icons.directions_car),
|
||||
const Choice(title: 'Выйти', icon: Icons.directions_bike)
|
||||
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 HomeView extends StatelessWidget {
|
||||
class HomeView extends StatefulWidget {
|
||||
@override
|
||||
_HomeViewState createState() => _HomeViewState();
|
||||
}
|
||||
|
||||
class _HomeViewState extends State<HomeView> {
|
||||
PageController pageController;
|
||||
int selectedTabIndex;
|
||||
DataService _dataService = locator<DataService>();
|
||||
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
// TODO: implement initState
|
||||
super.initState();
|
||||
selectedTabIndex = 0;
|
||||
pageController = new PageController(initialPage: selectedTabIndex);
|
||||
}
|
||||
|
||||
void _onSelectChoice(Choice choice) async {
|
||||
if(choice.command == 'exit') {
|
||||
|
||||
} else if (choice.command == 'update') {
|
||||
bool result = await _dataService.getDataFromServer(Redux.store.state.userState.user.token);
|
||||
print('result: $result');
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return ViewModelBuilder<HomeViewModel>.reactive(
|
||||
viewModelBuilder: () => HomeViewModel(
|
||||
authenticationService: Provider.of(context),
|
||||
navigationService: Provider.of(context)),
|
||||
onModelReady: (viewModel) {
|
||||
viewModel.initialize();
|
||||
viewModel.pageController =
|
||||
new PageController(initialPage: viewModel.tabIndex);
|
||||
},
|
||||
builder: (context, viewModel, child) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
title: Center(
|
||||
|
|
@ -61,12 +68,15 @@ class HomeView extends StatelessWidget {
|
|||
Icons.more_vert,
|
||||
color: menuColor,
|
||||
),
|
||||
onSelected: (s) {},
|
||||
onSelected: _onSelectChoice,
|
||||
itemBuilder: (BuildContext context) {
|
||||
return choices.map((Choice choice) {
|
||||
return PopupMenuItem<Choice>(
|
||||
value: choice,
|
||||
child: Text(choice.title),
|
||||
child: Row(children: <Widget>[
|
||||
Icon(choice.icon, color: primaryColor,),
|
||||
Text(choice.title)
|
||||
], ),
|
||||
);
|
||||
}).toList();
|
||||
},
|
||||
|
|
@ -76,17 +86,19 @@ class HomeView extends StatelessWidget {
|
|||
),
|
||||
body: PageView(
|
||||
onPageChanged: (index) {
|
||||
viewModel.tabIndex = index;
|
||||
setState(() {
|
||||
selectedTabIndex = index;
|
||||
});
|
||||
},
|
||||
controller: viewModel.pageController,
|
||||
controller: pageController,
|
||||
children: <Widget>[
|
||||
KassaTab(viewModel, 0),
|
||||
CalculatorTab(viewModel, 1),
|
||||
AdditionalTab(viewModel, 2)
|
||||
KassaTab(0),
|
||||
CalculatorTab(1),
|
||||
AdditionalTab(2),
|
||||
],
|
||||
),
|
||||
bottomNavigationBar: BottomNavigationBar(
|
||||
currentIndex: viewModel.tabIndex,
|
||||
currentIndex: selectedTabIndex,
|
||||
backgroundColor: menuColor,
|
||||
type: BottomNavigationBarType.shifting,
|
||||
items: [
|
||||
|
|
@ -111,7 +123,7 @@ class HomeView extends StatelessWidget {
|
|||
)),
|
||||
],
|
||||
onTap: (index) {
|
||||
viewModel.pageController.animateToPage(
|
||||
pageController.animateToPage(
|
||||
index,
|
||||
duration: const Duration(milliseconds: 300),
|
||||
curve: Curves.easeIn,
|
||||
|
|
@ -119,6 +131,5 @@ class HomeView extends StatelessWidget {
|
|||
},
|
||||
),
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,10 @@
|
|||
import 'package:aman_kassa_flutter/core/base/base_view_model.dart';
|
||||
import 'package:aman_kassa_flutter/core/entity/Category.dart';
|
||||
import 'package:aman_kassa_flutter/core/locator.dart';
|
||||
import 'package:aman_kassa_flutter/core/models/Choice.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/services/DataService.dart';
|
||||
import 'package:aman_kassa_flutter/core/services/authentication_service.dart';
|
||||
import 'package:aman_kassa_flutter/core/services/dialog_service.dart';
|
||||
|
||||
|
|
@ -10,12 +14,15 @@ import 'package:flutter/material.dart';
|
|||
class HomeViewModel extends BaseViewModel {
|
||||
NavigatorService _navigationService;
|
||||
AuthenticationService _authenticationService;
|
||||
DataService _dataService;
|
||||
final DialogService _dialogService = locator<DialogService>();
|
||||
|
||||
HomeViewModel({
|
||||
@required AuthenticationService authenticationService,
|
||||
@required NavigatorService navigationService,
|
||||
@required DataService dataService,
|
||||
}) : _authenticationService = authenticationService,
|
||||
_dataService = dataService,
|
||||
_navigationService = navigationService;
|
||||
|
||||
User _currentUser;
|
||||
|
|
@ -28,13 +35,48 @@ class HomeViewModel extends BaseViewModel {
|
|||
notifyListeners();
|
||||
}
|
||||
|
||||
void onSelected(Choice choice) async {
|
||||
log.i(choice.command);
|
||||
if(choice.command == 'exit') {
|
||||
bool result = await _authenticationService.logout(_currentUser.token);
|
||||
if (result) {
|
||||
_navigationService.replace(LoginViewRoute);
|
||||
}
|
||||
} else if (choice.command == 'update') {
|
||||
log.i(_authenticationService.currentUser.token);
|
||||
bool result = await _dataService.getDataFromServer(_authenticationService.currentUser.token);
|
||||
log.i(result);
|
||||
}
|
||||
}
|
||||
|
||||
PageController get pageController => this._pageController;
|
||||
PageController _pageController;
|
||||
set pageController(PageController pageController) {
|
||||
this._pageController = pageController;
|
||||
}
|
||||
|
||||
List<Object> _bottomSheetElements = [];
|
||||
List<Object> get bottomSheetElements => this._bottomSheetElements;
|
||||
int _parentId;
|
||||
void selectBottomElement(int parentId) async {
|
||||
// log.i('parentId=$parentId');
|
||||
// _parentId = parentId;
|
||||
// _bottomSheetElements.clear();
|
||||
// List<Category> categories = await _dataService.getCategoriesByParentId(parentId: parentId);
|
||||
// List<Category> goods = await _dataService.getGoodsByCategoryId(categoryId: parentId);
|
||||
// _bottomSheetElements.addAll(categories);
|
||||
// _bottomSheetElements.addAll(goods);
|
||||
// notifyListeners();
|
||||
}
|
||||
|
||||
|
||||
|
||||
String _text;
|
||||
get text => this._text;
|
||||
set text(String text) => this._text = text;
|
||||
|
||||
void initialize() {
|
||||
|
||||
_currentUser = _authenticationService.currentUser;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,20 +1,28 @@
|
|||
part of home_view;
|
||||
import 'package:aman_kassa_flutter/redux/state/user_state.dart';
|
||||
import 'package:aman_kassa_flutter/redux/store.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:aman_kassa_flutter/views/home/home_view_model.dart';
|
||||
import 'package:flutter_redux/flutter_redux.dart';
|
||||
import 'package:google_fonts/google_fonts.dart';
|
||||
|
||||
class AdditionalTab extends StatelessWidget {
|
||||
final HomeViewModel viewModel;
|
||||
final int index;
|
||||
|
||||
AdditionalTab(this.viewModel, this.index);
|
||||
|
||||
AdditionalTab(this.index);
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return StoreConnector<AppState, UserState>(
|
||||
converter: (store) => store.state.userState,
|
||||
builder: (context, vm) {
|
||||
return Container(
|
||||
child: Column(
|
||||
children: <Widget>[
|
||||
Text('AdditionalTab index:$index ${viewModel.currentUser.fullName} ',
|
||||
Text('AdditionalTab index:$index ${vm.user.fullName} ',
|
||||
style: GoogleFonts.lato(color: Colors.black87))
|
||||
],
|
||||
),
|
||||
);
|
||||
},
|
||||
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,10 +1,14 @@
|
|||
part of home_view;
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:aman_kassa_flutter/views/home/home_view_model.dart';
|
||||
import 'package:aman_kassa_flutter/widgets/components/calculator/calculator-buttons.dart';
|
||||
import 'package:aman_kassa_flutter/widgets/components/calculator/number-display.dart';
|
||||
|
||||
|
||||
|
||||
class CalculatorTab extends StatelessWidget {
|
||||
final HomeViewModel viewModel;
|
||||
final int index;
|
||||
|
||||
CalculatorTab(this.viewModel, this.index);
|
||||
CalculatorTab(this.index);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
|
|
|
|||
|
|
@ -1,4 +1,14 @@
|
|||
part of home_view;
|
||||
|
||||
import 'package:aman_kassa_flutter/core/models/ProductDao.dart';
|
||||
import 'package:aman_kassa_flutter/redux/actions/main_actions.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/home/tabs/kassaView/CatalogBottomSheet.dart';
|
||||
import 'package:aman_kassa_flutter/views/home/tabs/kassaView/ProductAddBottomSheet.dart';
|
||||
import 'package:aman_kassa_flutter/widgets/components/ProductListItem.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
|
||||
List<String> litems = [
|
||||
"1",
|
||||
|
|
@ -13,33 +23,14 @@ List<String> litems = [
|
|||
"2",
|
||||
"3",
|
||||
"4",
|
||||
"1",
|
||||
"2",
|
||||
"3",
|
||||
"4",
|
||||
"1",
|
||||
"2",
|
||||
"3",
|
||||
"4",
|
||||
"1",
|
||||
"2",
|
||||
"3",
|
||||
"4",
|
||||
"1",
|
||||
"2",
|
||||
"3",
|
||||
"4",
|
||||
"1",
|
||||
"2",
|
||||
"3",
|
||||
"4"
|
||||
"1"
|
||||
];
|
||||
|
||||
class KassaTab extends StatelessWidget {
|
||||
final HomeViewModel viewModel;
|
||||
|
||||
final int index;
|
||||
|
||||
KassaTab(this.viewModel, this.index);
|
||||
KassaTab(this.index);
|
||||
|
||||
Widget buildItem(BuildContext ctxt, int index) {
|
||||
return ProductListItem(
|
||||
|
|
@ -49,9 +40,7 @@ class KassaTab extends StatelessWidget {
|
|||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
backgroundColor: fillColor,
|
||||
body: Padding(
|
||||
return Padding(
|
||||
padding: EdgeInsets.all(4),
|
||||
child: Column(
|
||||
children: <Widget>[
|
||||
|
|
@ -67,7 +56,7 @@ class KassaTab extends StatelessWidget {
|
|||
"Добавить",
|
||||
style: buttonBigTitleTextStyle,
|
||||
),
|
||||
onPressed: () => null,
|
||||
onPressed: () { showModalBottomSheetCatalog(context, 'add');},
|
||||
),
|
||||
),
|
||||
),
|
||||
|
|
@ -81,7 +70,7 @@ class KassaTab extends StatelessWidget {
|
|||
"Каталог",
|
||||
style: buttonBigTitleTextStyle,
|
||||
),
|
||||
onPressed: () => null,
|
||||
onPressed: () { showModalBottomSheetCatalog(context, 'catalog');},
|
||||
),
|
||||
),
|
||||
),
|
||||
|
|
@ -129,7 +118,30 @@ class KassaTab extends StatelessWidget {
|
|||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
void showModalBottomSheetCatalog(BuildContext context, String action) {
|
||||
showModalBottomSheet(
|
||||
context: context,
|
||||
isScrollControlled: true,
|
||||
backgroundColor: Colors.transparent,
|
||||
builder: (context){
|
||||
return DraggableScrollableSheet(
|
||||
initialChildSize: 0.8,
|
||||
maxChildSize: 0.95,
|
||||
minChildSize: 0.5,
|
||||
builder: (BuildContext context, ScrollController scrollController) {
|
||||
if( action == 'add') {
|
||||
return ProductAddBottomSheet();
|
||||
} else {
|
||||
return CatalogBottomSheet(scrollController: scrollController,);
|
||||
}
|
||||
},
|
||||
);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,104 @@
|
|||
import 'package:aman_kassa_flutter/core/entity/Category.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/redux/state/main_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:flutter/material.dart';
|
||||
import 'package:flutter_redux/flutter_redux.dart';
|
||||
|
||||
class CatalogBottomSheet extends StatelessWidget {
|
||||
final ScrollController scrollController;
|
||||
|
||||
CatalogBottomSheet({this.scrollController});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return StoreConnector<AppState, MainState>(
|
||||
converter: (store) => store.state.mainState,
|
||||
onInit: (store) => Redux.store.dispatch(selectBottomElement(0)),
|
||||
builder: (context, vm) {
|
||||
return WillPopScope(
|
||||
onWillPop: () {
|
||||
if (vm.prevCategories.length > 0) {
|
||||
Redux.store.dispatch(backBottomElement);
|
||||
} else
|
||||
Navigator.pop(context);
|
||||
return new Future(() => false);
|
||||
},
|
||||
child: Scaffold(
|
||||
appBar: AppBar(
|
||||
title: Text(
|
||||
vm.prevCategories.isNotEmpty
|
||||
? vm.prevCategories?.last?.name
|
||||
: '',
|
||||
style: TextStyle(color: Colors.black45),
|
||||
),
|
||||
iconTheme: IconThemeData(color: Colors.black),
|
||||
backgroundColor: whiteColor,
|
||||
elevation: 3,
|
||||
leading: IconButton(
|
||||
icon: Icon(vm.prevCategories.length > 0
|
||||
? Icons.arrow_back
|
||||
: Icons.close),
|
||||
onPressed: () {
|
||||
if (vm.prevCategories.length > 0) {
|
||||
Redux.store.dispatch(backBottomElement);
|
||||
} else
|
||||
Navigator.pop(context);
|
||||
},
|
||||
),
|
||||
),
|
||||
body: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||
children: <Widget>[
|
||||
Expanded(
|
||||
child: ListView.builder(
|
||||
controller: scrollController,
|
||||
itemCount: vm.bottomSheetElements.length,
|
||||
itemBuilder: (context, index) {
|
||||
var el = vm.bottomSheetElements[index];
|
||||
String name;
|
||||
if (el is Category) {
|
||||
Category category = el;
|
||||
name = category.name;
|
||||
} else if (el is Good) {
|
||||
Good good = el;
|
||||
name = good.name;
|
||||
}
|
||||
return Card(
|
||||
child: ListTile(
|
||||
leading: Icon(
|
||||
el is Category ? Icons.layers : Icons.move_to_inbox,
|
||||
size: 40,
|
||||
),
|
||||
title: Text(name),
|
||||
onTap: () {
|
||||
if (el is Category) {
|
||||
Redux.store.dispatch(selectBottomElement(el.id));
|
||||
}
|
||||
},
|
||||
trailing:
|
||||
el is Category ? Icon(Icons.chevron_right) : null,
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
RaisedButton(
|
||||
child: Text(
|
||||
'Отмена',
|
||||
style: buttonBigTitleTextStyle,
|
||||
),
|
||||
color: redColor,
|
||||
onPressed: () {
|
||||
Navigator.pop(context);
|
||||
}),
|
||||
],
|
||||
)),
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
import 'package:aman_kassa_flutter/shared/app_colors.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class ProductAddBottomSheet extends StatelessWidget {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Container(
|
||||
decoration: BoxDecoration(
|
||||
color: whiteColor
|
||||
),
|
||||
child: Text('ProductAddBottomSheet'),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,15 +1,13 @@
|
|||
library login_view;
|
||||
|
||||
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/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/widgets/fields/busy_button.dart';
|
||||
import 'package:aman_kassa_flutter/widgets/fields/input_field.dart';
|
||||
import 'package:aman_kassa_flutter/widgets/fields/text_link.dart';
|
||||
import 'package:google_fonts/google_fonts.dart';
|
||||
import 'package:flutter_redux/flutter_redux.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:stacked/stacked.dart';
|
||||
import 'login_view_model.dart';
|
||||
|
||||
class LoginView extends StatelessWidget {
|
||||
final emailController = TextEditingController(text: 'test@kkm-kassa.kz');
|
||||
|
|
@ -18,30 +16,16 @@ class LoginView extends StatelessWidget {
|
|||
final FocusNode passwordNode = new FocusNode();
|
||||
final GlobalKey<ScaffoldState> _scaffoldKey = new GlobalKey<ScaffoldState>();
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
login(LoginViewModel viewModel) async {
|
||||
String message = await viewModel.login(
|
||||
email: emailController.text.trim(),
|
||||
password: passwordController.text);
|
||||
if (message != null) {
|
||||
_scaffoldKey.currentState.showSnackBar(new SnackBar(
|
||||
content: new Text(
|
||||
message,
|
||||
style: GoogleFonts.lato(),
|
||||
)));
|
||||
}
|
||||
_pressBtnEnter() async {
|
||||
Redux.store.dispatch(authenticate(emailController.text, passwordController.text));
|
||||
}
|
||||
|
||||
//LoginViewModel viewModel = LoginViewModel();
|
||||
return ViewModelBuilder<LoginViewModel>.reactive(
|
||||
viewModelBuilder: () => LoginViewModel(
|
||||
authenticationService: Provider.of(context),
|
||||
navigationService: Provider.of(context)),
|
||||
onModelReady: (viewModel) {
|
||||
// Do something once your viewModel is initialized
|
||||
},
|
||||
builder: (context, viewModel, child) {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return StoreConnector<AppState, UserState>(
|
||||
converter: (store) => store.state.userState,
|
||||
builder: (context, vm) {
|
||||
print('build');
|
||||
return Scaffold(
|
||||
key: _scaffoldKey,
|
||||
backgroundColor: fillColor,
|
||||
|
|
@ -62,7 +46,7 @@ class LoginView extends StatelessWidget {
|
|||
controller: emailController,
|
||||
textInputType: TextInputType.emailAddress,
|
||||
nextFocusNode: passwordNode,
|
||||
additionalNote: viewModel.messageEmail,
|
||||
additionalNote: vm.loginFormMessage.email,
|
||||
),
|
||||
verticalSpaceSmall,
|
||||
InputField(
|
||||
|
|
@ -70,9 +54,8 @@ class LoginView extends StatelessWidget {
|
|||
password: true,
|
||||
controller: passwordController,
|
||||
fieldFocusNode: passwordNode,
|
||||
additionalNote: viewModel.messagePassword,
|
||||
enterPressed: () => login(viewModel),
|
||||
),
|
||||
additionalNote: vm.loginFormMessage.password,
|
||||
enterPressed: _pressBtnEnter),
|
||||
verticalSpaceMedium,
|
||||
Row(
|
||||
mainAxisSize: MainAxisSize.max,
|
||||
|
|
@ -80,8 +63,8 @@ class LoginView extends StatelessWidget {
|
|||
children: [
|
||||
BusyButton(
|
||||
title: 'Войти',
|
||||
busy: viewModel.busy,
|
||||
onPressed: () => login(viewModel),
|
||||
busy: vm.isLoading,
|
||||
onPressed: _pressBtnEnter,
|
||||
)
|
||||
],
|
||||
),
|
||||
|
|
@ -95,4 +78,6 @@ class LoginView extends StatelessWidget {
|
|||
));
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,74 +0,0 @@
|
|||
import 'package:aman_kassa_flutter/core/base/base_view_model.dart';
|
||||
import 'package:aman_kassa_flutter/core/route_names.dart';
|
||||
import 'package:aman_kassa_flutter/core/services/authentication_service.dart';
|
||||
import 'package:aman_kassa_flutter/core/services/navigator_service.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:aman_kassa_flutter/core/models/authResponse.dart';
|
||||
|
||||
class LoginViewModel extends BaseViewModel {
|
||||
|
||||
//service
|
||||
NavigatorService _navigationService;
|
||||
AuthenticationService _authenticationService;
|
||||
|
||||
//private var
|
||||
String _messageEmail;
|
||||
String _messagePassword;
|
||||
|
||||
//public getter setter
|
||||
get messageEmail => this._messageEmail;
|
||||
set messageEmail(String message) {
|
||||
this._messageEmail = message;
|
||||
notifyListeners();
|
||||
}
|
||||
get messagePassword => this._messagePassword;
|
||||
set messagePassword(String message) {
|
||||
this._messagePassword = message;
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
|
||||
LoginViewModel({
|
||||
@required AuthenticationService authenticationService,
|
||||
@required NavigatorService navigationService,
|
||||
}) :
|
||||
_authenticationService = authenticationService ,
|
||||
_navigationService = navigationService;
|
||||
|
||||
|
||||
Future<String> login({String email, String password}) async {
|
||||
String result;
|
||||
busy = true;
|
||||
try {
|
||||
AuthBody response = await _authenticationService.loginWithEmail(email: email, password: password);
|
||||
|
||||
if(response!=null) {
|
||||
if(response.user != null){
|
||||
_navigationService.replace(HomeViewRoute);
|
||||
} else {
|
||||
// show error on validate
|
||||
if(response.email?.isEmpty == false){
|
||||
messageEmail = response.email.join(",");
|
||||
} else {
|
||||
messageEmail = null;
|
||||
}
|
||||
if(response.password?.isEmpty == false){
|
||||
messagePassword = response.password.join(",");
|
||||
} else {
|
||||
messagePassword = null;
|
||||
}
|
||||
//return meesage on snackbar for user screen
|
||||
if(response.message!=null) {
|
||||
result = response.message;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} finally {
|
||||
busy = false ;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
// Add ViewModel specific code here
|
||||
}
|
||||
|
|
@ -1,20 +1,29 @@
|
|||
library home_view;
|
||||
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
import 'start_up_view_model.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/store.dart';
|
||||
import 'package:flutter_redux/flutter_redux.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:stacked/stacked.dart';
|
||||
|
||||
class StartUpView extends StatelessWidget {
|
||||
|
||||
class StartUpView extends StatefulWidget {
|
||||
@override
|
||||
_StartUpViewState createState() => _StartUpViewState();
|
||||
}
|
||||
|
||||
class _StartUpViewState extends State<StartUpView> {
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
// TODO: implement initState
|
||||
super.initState();
|
||||
Redux.store.dispatch(checkUserAction);
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return ViewModelBuilder<StartUpViewModel>.reactive(
|
||||
viewModelBuilder: () => StartUpViewModel(authenticationService: Provider.of(context), navigationService: Provider.of(context)),
|
||||
onModelReady: (viewModel) {
|
||||
viewModel.handleStartUpLogic();
|
||||
},
|
||||
builder: (context, viewModel, child) {
|
||||
return StoreConnector<AppState, UserState>(
|
||||
converter: (store) => store.state.userState,
|
||||
builder: (context, userState) {
|
||||
return Scaffold(
|
||||
body: Center(
|
||||
child: Column(
|
||||
|
|
@ -25,6 +34,8 @@ class StartUpView extends StatelessWidget {
|
|||
height: 200,
|
||||
child: Image.asset('assets/images/icon_large.png'),
|
||||
),
|
||||
Text('${userState.isLoading}'),
|
||||
Text('${userState.isAuthenticated}'),
|
||||
CircularProgressIndicator(
|
||||
strokeWidth: 3,
|
||||
valueColor: AlwaysStoppedAnimation(
|
||||
|
|
|
|||
|
|
@ -1,33 +0,0 @@
|
|||
import 'package:aman_kassa_flutter/core/base/base_view_model.dart';
|
||||
import 'package:aman_kassa_flutter/core/route_names.dart';
|
||||
import 'package:aman_kassa_flutter/core/services/authentication_service.dart';
|
||||
import 'package:aman_kassa_flutter/core/services/navigator_service.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class StartUpViewModel extends BaseViewModel {
|
||||
NavigatorService _navigationService;
|
||||
AuthenticationService _authenticationService;
|
||||
|
||||
StartUpViewModel({
|
||||
@required AuthenticationService authenticationService,
|
||||
@required NavigatorService navigationService,
|
||||
}) :
|
||||
_authenticationService = authenticationService ,
|
||||
_navigationService = navigationService;
|
||||
|
||||
|
||||
|
||||
Future handleStartUpLogic() async {
|
||||
// Register for push notifications
|
||||
//await _pushNotificationService.initialise();
|
||||
|
||||
var hasLoggedInUser = await _authenticationService.isUserLoggedIn('test');
|
||||
log.i('hasLoggedInUser $hasLoggedInUser');
|
||||
if (hasLoggedInUser) {
|
||||
//_navigationService.navigateTo(HomeViewRoute);
|
||||
_navigationService.replace(HomeViewRoute);
|
||||
} else {
|
||||
_navigationService.replace(LoginViewRoute);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,57 +1,81 @@
|
|||
import 'package:aman_kassa_flutter/shared/shared_styles.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:aman_kassa_flutter/shared/app_colors.dart';
|
||||
import 'package:aman_kassa_flutter/core/models/ProductDao.dart';
|
||||
|
||||
class ProductListItem extends StatelessWidget {
|
||||
|
||||
ProductDao item;
|
||||
|
||||
ProductListItem({
|
||||
this.item
|
||||
});
|
||||
ProductListItem({this.item});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Container(
|
||||
padding: EdgeInsets.symmetric(vertical: 8, horizontal: 4),
|
||||
return Padding(
|
||||
padding: EdgeInsets.symmetric(vertical: 4, horizontal: 4),
|
||||
child: Column(
|
||||
children: <Widget>[
|
||||
Container(
|
||||
child: Row(
|
||||
children: <Widget>[
|
||||
Expanded(
|
||||
child: Container(
|
||||
color: whiteColor,
|
||||
padding: EdgeInsets.symmetric(vertical: 8, horizontal: 4),
|
||||
child: Text(item.name)
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
child: Container(
|
||||
color: whiteColor,
|
||||
padding: EdgeInsets.symmetric(vertical: 8, horizontal: 4),
|
||||
child: Text('${item.price?.toString()} x ${item.count?.toString()}', textAlign: TextAlign.right)
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
Row(
|
||||
children: <Widget>[
|
||||
Expanded(
|
||||
child: Container(
|
||||
color: whiteColor,
|
||||
padding: EdgeInsets.symmetric(vertical: 8, horizontal: 4),
|
||||
child: Text(item.name)
|
||||
),
|
||||
padding: const EdgeInsets.symmetric(vertical: 8, horizontal: 4),
|
||||
child: Text(item.name, style: productTextStyle,)),
|
||||
),
|
||||
Expanded(
|
||||
child: Container(child: Text(item.name)),
|
||||
child: Container(
|
||||
padding: const EdgeInsets.symmetric(vertical: 8, horizontal: 4),
|
||||
child: Text(
|
||||
'${item.price?.toString()} x ${item.count?.toString()}',
|
||||
textAlign: TextAlign.right, style: productTextStyle)),
|
||||
)
|
||||
],
|
||||
),
|
||||
Container(
|
||||
child: Row(
|
||||
children: <Widget>[
|
||||
Expanded(
|
||||
flex: 1,
|
||||
child: Container(),
|
||||
),
|
||||
Expanded(
|
||||
flex: 1,
|
||||
child: Container(
|
||||
//margin: const EdgeInsets.symmetric(horizontal: 4),
|
||||
child: Row(
|
||||
children: <Widget>[
|
||||
buildClipRect(primaryColor,Icons.remove, () {}),
|
||||
buildClipRect(primaryColor,Icons.add, () {}),
|
||||
Expanded(
|
||||
child: Container(
|
||||
),
|
||||
),
|
||||
buildClipRect(redColor,Icons.close, () {}),
|
||||
],
|
||||
)),
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
Divider()
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
ClipRect buildClipRect(Color color, IconData icon, VoidCallback onPress) {
|
||||
return ClipRect(
|
||||
child: Container(
|
||||
margin: const EdgeInsets.all(5),
|
||||
decoration: BoxDecoration(
|
||||
color: color
|
||||
),
|
||||
height: 35,
|
||||
width: 35,
|
||||
child: IconButton(
|
||||
icon: Icon(icon, color: whiteColor, size: 20),
|
||||
onPressed: onPress,
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ class CalculatorButton extends StatelessWidget {
|
|||
child: Container(
|
||||
decoration: BoxDecoration(
|
||||
border: Border.all(
|
||||
color: Color.fromRGBO(0, 0, 0, 0.1),
|
||||
color: const Color.fromRGBO(0, 0, 0, 0.1),
|
||||
width: 0.5,
|
||||
),
|
||||
),
|
||||
|
|
@ -24,7 +24,7 @@ class CalculatorButton extends StatelessWidget {
|
|||
text,
|
||||
style: TextStyle(fontSize: 25, fontWeight: FontWeight.w500),
|
||||
),
|
||||
padding: EdgeInsets.all(15),
|
||||
padding: const EdgeInsets.all(15),
|
||||
highlightColor: Colors.blueGrey[100],
|
||||
splashColor: Colors.blueAccent[100],
|
||||
)));
|
||||
|
|
|
|||
51
pubspec.lock
51
pubspec.lock
|
|
@ -83,6 +83,13 @@ packages:
|
|||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.0.2"
|
||||
flutter_redux:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: flutter_redux
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.6.0"
|
||||
flutter_test:
|
||||
dependency: "direct dev"
|
||||
description: flutter
|
||||
|
|
@ -173,7 +180,7 @@ packages:
|
|||
source: hosted
|
||||
version: "1.6.4"
|
||||
path_provider:
|
||||
dependency: transitive
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: path_provider
|
||||
url: "https://pub.dartlang.org"
|
||||
|
|
@ -242,6 +249,20 @@ packages:
|
|||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.1.3"
|
||||
redux:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: redux
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "4.0.0"
|
||||
redux_thunk:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: redux_thunk
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.3.0"
|
||||
responsive_builder:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
|
|
@ -254,6 +275,13 @@ packages:
|
|||
description: flutter
|
||||
source: sdk
|
||||
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:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
|
@ -261,6 +289,20 @@ packages:
|
|||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.7.0"
|
||||
sqflite:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: sqflite
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.3.0+2"
|
||||
sqflite_common:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: sqflite_common
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.0.1"
|
||||
stack_trace:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
|
@ -289,6 +331,13 @@ packages:
|
|||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.0.5"
|
||||
synchronized:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: synchronized
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.2.0"
|
||||
term_glyph:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
|
|
|||
|
|
@ -7,6 +7,9 @@ dependencies:
|
|||
flutter:
|
||||
sdk: flutter
|
||||
cupertino_icons: ^0.1.2
|
||||
redux: ^4.0.0
|
||||
flutter_redux: ^0.6.0
|
||||
redux_thunk: ^0.3.0
|
||||
stacked : ^1.5.2
|
||||
provider_architecture: ^1.0.3
|
||||
responsive_builder: ^0.1.4
|
||||
|
|
@ -15,8 +18,11 @@ dependencies:
|
|||
get_it: ^3.0.3
|
||||
equatable: ^1.1.1
|
||||
http: ^0.12.1
|
||||
sqflite: ^1.3.0
|
||||
path_provider: ^1.6.9
|
||||
google_fonts: ^1.1.0
|
||||
flutter_boom_menu: ^1.0.2
|
||||
sliding_up_panel: ^1.0.2
|
||||
material_design_icons_flutter: ^4.0.5345
|
||||
dev_dependencies:
|
||||
flutter_test:
|
||||
|
|
|
|||
Loading…
Reference in New Issue