floating action and bottom bar release

4.4
Serik.Uvaissov 2020-05-26 20:32:41 +06:00
parent 46302aed18
commit 3e7007ab63
12 changed files with 388 additions and 151 deletions

View File

@ -1,7 +1,7 @@
import '../core/services/ApiService.dart'; import '../core/services/ApiService.dart';
import '../core/services/authentication_service.dart'; import '../core/services/dialog_service.dart';
import '../core/logger.dart'; import '../core/logger.dart';
import '../core/services/navigator_service.dart'; import '../core/services/navigator_service.dart';
import 'package:get_it/get_it.dart'; import 'package:get_it/get_it.dart';
@ -17,6 +17,8 @@ class LocatorInjector {
locator.registerLazySingleton<ApiService>(() => ApiService()); locator.registerLazySingleton<ApiService>(() => ApiService());
_log.d('Initializing Navigator Service'); _log.d('Initializing Navigator Service');
locator.registerLazySingleton<NavigatorService>(() => NavigatorService()); locator.registerLazySingleton<NavigatorService>(() => NavigatorService());
_log.d('Initializing Dialog Service');
locator.registerLazySingleton<DialogService>(() => DialogService());
} }
} }

View File

@ -1,43 +1,52 @@
import 'dart:developer' as prefix0; //import 'dart:developer' as prefix0;
import 'package:logger/logger.dart'; import 'package:logger/logger.dart';
class SimpleLogPrinter extends LogPrinter { // class SimpleLogPrinter extends LogPrinter {
static int counter = 0; // static int counter = 0;
final String className; // final String className;
SimpleLogPrinter(this.className); // SimpleLogPrinter(this.className);
@override // @override
List<String> log(LogEvent event) { // List<String> log(LogEvent event) {
prefix0.log( // prefix0.log(
event.message, // event.message,
time: DateTime.now(), // time: DateTime.now(),
level: () { // level: () {
switch (event.level) { // switch (event.level) {
case Level.verbose: // case Level.verbose:
return 0; // return 0;
case Level.debug: // case Level.debug:
return 500; // return 500;
case Level.info: // case Level.info:
return 0; // return 0;
case Level.warning: // case Level.warning:
return 1500; // return 1500;
case Level.error: // case Level.error:
return 2000; // return 2000;
case Level.wtf: // case Level.wtf:
return 2000; // return 2000;
default: // default:
return 2000; // return 2000;
} // }
}(), // }(),
name: className, // name: className,
error: event.error, // error: event.error,
sequenceNumber: counter += 1, // sequenceNumber: counter += 1,
); // );
return []; // return [];
} // }
} // }
Logger getLogger(String className) { Logger getLogger(String className) {
return Logger(printer: SimpleLogPrinter(className)); //return Logger(printer: SimpleLogPrinter(className));
return Logger(
printer: PrettyPrinter(
methodCount: 2, // number of method calls to be displayed
errorMethodCount: 8, // number of method calls if stacktrace is provided
lineLength: 120, // width of the output
colors: true, // Colorful log messages
printEmojis: true, // Print an emoji for each log message
printTime: false // Should each log print contain a timestamp
));
} }

View File

@ -1,20 +1,22 @@
class User { class User {
final String token;
final String fullName; final String name;
final String email; final String email;
final String fullName;
final String token;
int appCompanyId;
int kassaId;
User({this.token, this.fullName, this.email}); User({this.email, this.fullName, this.name, this.token, this.appCompanyId, this.kassaId});
User.fromData(Map<String, dynamic> data) factory User.fromJson(Map<String, dynamic> json) {
: token = data['api_token'], return User (
fullName = data['fullName'], name: json['name'],
email = data['email']; email: json['mail'],
token: json['api_token'],
Map<String, dynamic> toJson() { fullName: json['fullname'],
return { appCompanyId: json['app_company_id'] as int,
'api_token': token, kassaId: json['kassa_id'] as int,
'fullName': fullName, );
'email': email,
};
} }
} }

View File

@ -3,6 +3,8 @@ 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/models/session.dart'; import 'package:aman_kassa_flutter/core/models/session.dart';
import '../models/authResponse.dart';
import 'package:http/http.dart' as http; import 'package:http/http.dart' as http;
@ -12,52 +14,38 @@ class ApiService extends BaseService {
var client = new http.Client(); var client = new http.Client();
Future<AuthBody> authenticate(String email, String password) async {
Map<String, String> requestBody = <String, String>{
Future<Session> isActive(String token) async { 'email': email,
// var map = new Map<String, dynamic>(); 'password': password
// map['api_token'] = token; };
// var response = await client.post( var response = await requestFormData('/authenticate', requestBody);
// '$endpoint/test_auth', final respStr = await response.stream.bytesToString();
// headers: { print(respStr);
// HttpHeaders.contentTypeHeader: "multipart/form-data", AuthResponse aman = AuthResponse.fromJson(json.decode(respStr));
// HttpHeaders.cacheControlHeader: "no-cache" return aman.body;
// },
// body: map);
// print(response.body);
// return Session.fromData(token,json.decode(response.body));
Map<String, String> requestBody = <String,String>{
'api_token':token
};
Map<String, String> headers= <String,String>{
HttpHeaders.contentTypeHeader: "multipart/form-data",
HttpHeaders.cacheControlHeader: "no-cache"
};
var uri = Uri.parse('$endpoint/test_auth');
var request = http.MultipartRequest('POST', uri)
..headers.addAll(headers) //if u have headers, basic auth, token bearer... Else remove line
..fields.addAll(requestBody);
var response = await request.send();
final respStr = await response.stream.bytesToString();
print(respStr);
return Session.fromData(token,json.decode(respStr));
} }
// Future<List<Post>> getPostsForUser(int userId) async { Future<Session> isActive(String token) async {
// var posts = List<Post>(); Map<String, String> requestBody = <String, String>{'api_token': token};
// // Get user posts for id var response = await requestFormData('/test_auth', requestBody);
// var response = await client.get('$endpoint/posts?userId=$userId'); final respStr = await response.stream.bytesToString();
return Session.fromData(token, json.decode(respStr)['body']);
}
// // parse into List Future<http.StreamedResponse> requestFormData(
// var parsed = json.decode(response.body) as List<dynamic>; String point, Map<String, String> requestBody) async {
Map<String, String> headers = <String, String>{
HttpHeaders.contentTypeHeader: "multipart/form-data",
HttpHeaders.cacheControlHeader: "no-cache"
};
// // loop and convert each item to Post var uri = Uri.parse('$endpoint$point');
// for (var post in parsed) { var request = http.MultipartRequest('POST', uri)
// posts.add(Post.fromJson(post)); ..headers.addAll(
// } headers) //if u have headers, basic auth, token bearer... Else remove line
..fields.addAll(requestBody);
// return posts; return await request.send();
// } }
} }

View File

@ -1,13 +1,12 @@
import 'package:aman_kassa_flutter/core/base/base_service.dart'; import 'package:aman_kassa_flutter/core/base/base_service.dart';
import 'package:aman_kassa_flutter/core/models/session.dart'; import 'package:aman_kassa_flutter/core/models/session.dart';
import 'package:aman_kassa_flutter/core/models/user.dart'; import 'package:aman_kassa_flutter/core/models/user.dart';
import 'package:aman_kassa_flutter/core/models/authResponse.dart';
import 'package:flutter/foundation.dart'; import 'package:flutter/foundation.dart';
import 'ApiService.dart'; import 'ApiService.dart';
class AuthenticationService extends BaseService { class AuthenticationService extends BaseService {
final ApiService _api; final ApiService _api;
AuthenticationService({ApiService api}) : _api = api; AuthenticationService({ApiService api}) : _api = api;
@ -18,31 +17,28 @@ class AuthenticationService extends BaseService {
Session _session; Session _session;
Session get currentSession => _session; Session get currentSession => _session;
// Future loginWithEmail({ Future<AuthBody> loginWithEmail({
// @required String email, @required String email,
// @required String password, @required String password,
// }) async { }) async {
// try { try {
// User result = await _api.getUserProfile(123); AuthBody result = await _api.authenticate(email, password);
// _currentUser = result; if (result.user != null) {
// return result != null; _currentUser = result.user;
// } catch (e) { }
// return e.message; return result;
// } } catch (e) {
// } print(e);
return null;
}
}
Future<bool> isUserLoggedIn(token) async { Future<bool> isUserLoggedIn(String token) async {
Session session = await _api.isActive(token); Session session = await _api.isActive(token);
if("OK" == session.message){ if ("OK" == session.message) {
_session = session; _session = session;
return true; return true;
} }
return false; return false;
} }
// Future<bool> isUserLoggedIn() async {
// var user = await _firebaseAuth.currentUser();
// await _populateCurrentUser(user);
// return user != null;
// }
} }

View File

@ -6,6 +6,8 @@ import 'core/locator.dart';
import 'core/providers.dart'; import 'core/providers.dart';
import 'core/router.dart'; import 'core/router.dart';
import 'core/services/navigator_service.dart'; import 'core/services/navigator_service.dart';
import 'core/services/dialog_service.dart';
import './widgets/dialog_manager.dart';
//pages //pages
import 'views/start_up/start_up_view.dart'; import 'views/start_up/start_up_view.dart';
@ -24,6 +26,17 @@ class MainApplication extends StatelessWidget {
return MultiProvider( return MultiProvider(
providers: ProviderInjector.providers.toList(), providers: ProviderInjector.providers.toList(),
child: MaterialApp( child: MaterialApp(
theme: ThemeData(
//primaryColor: blueColor,
backgroundColor: Colors.white,
scaffoldBackgroundColor: Colors.white,
),
debugShowCheckedModeBanner: false,
builder: (context, child) => Navigator(
key: locator<DialogService>().dialogNavigationKey,
onGenerateRoute: (settings) => MaterialPageRoute(
builder: (context) => DialogManager(child: child)),
),
navigatorKey: locator<NavigatorService>().navigatorKey, navigatorKey: locator<NavigatorService>().navigatorKey,
home: StartUpView(), // first page home: StartUpView(), // first page
onGenerateRoute: generateRoute, onGenerateRoute: generateRoute,

View File

@ -1,22 +1,110 @@
library home_view; library home_view;
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:stacked/stacked.dart'; import 'package:stacked/stacked.dart';
import 'home_view_model.dart'; import 'home_view_model.dart';
class HomeView extends StatelessWidget { class HomeView extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return ViewModelBuilder<HomeViewModel>.reactive( return ViewModelBuilder<HomeViewModel>.reactive(
viewModelBuilder: () => HomeViewModel(), viewModelBuilder: () => HomeViewModel(
authenticationService: Provider.of(context),
navigationService: Provider.of(context)),
onModelReady: (viewModel) { onModelReady: (viewModel) {
viewModel.busy = true; viewModel.initialize();
viewModel.pageController = new PageController(initialPage: viewModel.tabIndex);
}, },
builder: (context, viewModel, child) { builder: (context, viewModel, child) {
return Scaffold( return Scaffold(
body: Center(child: Text('HomeView')), body: PageView(
onPageChanged: (index) {
viewModel.tabIndex = index;
},
controller: viewModel.pageController,
children: <Widget>[
KassaTab(viewModel, 0),
PrefencesTab(viewModel, 1)
],
),
bottomNavigationBar: BottomNavigationBar(
currentIndex: viewModel.tabIndex,
type: BottomNavigationBarType.shifting,
items: [
BottomNavigationBarItem(
icon: Icon(Icons.add_shopping_cart,
color: Color.fromARGB(255, 0, 0, 0)),
title: new Text(
'Касса',
style: TextStyle(color: Colors.black),
)),
BottomNavigationBarItem(
icon: Icon(Icons.assignment,
color: Color.fromARGB(255, 0, 0, 0)),
title: new Text(
'Опции',
style: TextStyle(color: Colors.black),
)),
],
onTap: (index) {
viewModel.pageController.animateToPage(
index,
duration: const Duration(milliseconds: 300),
curve: Curves.easeIn,
);
},
),
); );
}); });
} }
}
class KassaTab extends StatelessWidget {
final HomeViewModel viewModel;
final int index;
KassaTab(this.viewModel, this.index);
@override
Widget build(BuildContext context) {
// TODO: implement build
return Scaffold(
body: Column(
children: <Widget>[
Text('KassaTab index:$index ${viewModel.currentUser.fullName} ')
],
),
floatingActionButton: viewModel.tabIndex == 0
? FloatingActionButton(
onPressed: () {},
child: Icon(
Icons.add,
color: Colors.black,
size: 45,
),
backgroundColor: Colors.white,
)
: null);
}
}
class PrefencesTab extends StatelessWidget {
final HomeViewModel viewModel;
final int index;
PrefencesTab(this.viewModel, this.index);
@override
Widget build(BuildContext context) {
// TODO: implement build
return Container(
child: Column(
children: <Widget>[
Text('PrefencesTab index:$index ${viewModel.currentUser.fullName} ')
],
),
);
}
} }

View File

@ -1,22 +1,42 @@
import 'package:aman_kassa_flutter/core/base/base_view_model.dart'; import 'package:aman_kassa_flutter/core/base/base_view_model.dart';
import 'package:aman_kassa_flutter/core/locator.dart'; import 'package:aman_kassa_flutter/core/locator.dart';
import 'package:aman_kassa_flutter/core/models/user.dart';
import 'package:aman_kassa_flutter/core/services/authentication_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:flutter/material.dart';
class HomeViewModel extends BaseViewModel { class HomeViewModel extends BaseViewModel {
final NavigatorService _navigationService = locator<NavigatorService>(); NavigatorService _navigationService;
int _counter; AuthenticationService _authenticationService;
final DialogService _dialogService = locator<DialogService>();
HomeViewModel({int counter = 0}) : this._counter = counter; User _currentUser ;
User get currentUser => _currentUser;
int get counter => this._counter; HomeViewModel({
set counter(int value) { @required AuthenticationService authenticationService,
this._counter = value; @required NavigatorService navigationService,
}) :
_authenticationService = authenticationService ,
_navigationService = navigationService;
int _tabIndex = 0;
int get tabIndex => this._tabIndex;
PageController get pageController => this._pageController;
PageController _pageController;
set pageController(PageController pageController) {
this._pageController = pageController;
}
set tabIndex(int index) {
this._tabIndex = index;
notifyListeners(); notifyListeners();
} }
void increment() => this.counter += 1; void initialize() {
_currentUser = _authenticationService.currentUser;
}
} }

View File

@ -4,28 +4,43 @@ 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:aman_kassa_flutter/widgets/fields/text_link.dart';
import 'package:google_fonts/google_fonts.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:stacked/stacked.dart'; import 'package:stacked/stacked.dart';
import 'login_view_model.dart'; import 'login_view_model.dart';
class LoginView extends StatelessWidget { class LoginView extends StatelessWidget {
final emailController = TextEditingController(); final emailController = TextEditingController(text: 'test@kkm-kassa.kz');
final passwordController = TextEditingController(); final passwordController = TextEditingController(text: 'qwe123');
final FocusNode passwordNode = new FocusNode(); final FocusNode passwordNode = new FocusNode();
final GlobalKey<ScaffoldState> _scaffoldKey = new GlobalKey<ScaffoldState>();
@override @override
Widget build(BuildContext context) { 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(),)));
}
}
//LoginViewModel viewModel = LoginViewModel(); //LoginViewModel viewModel = LoginViewModel();
return ViewModelBuilder<LoginViewModel>.reactive( return ViewModelBuilder<LoginViewModel>.reactive(
viewModelBuilder: () => LoginViewModel(), viewModelBuilder: () => LoginViewModel(
authenticationService: Provider.of(context),
navigationService: Provider.of(context)),
onModelReady: (viewModel) { onModelReady: (viewModel) {
// Do something once your viewModel is initialized // Do something once your viewModel is initialized
}, },
builder: (context, viewModel, child) { builder: (context, viewModel, child) {
return Scaffold( return Scaffold(
//backgroundColor: Colors.white, key: _scaffoldKey,
body: Padding( //backgroundColor: Colors.white,
body: Padding(
padding: const EdgeInsets.symmetric(horizontal: 50), padding: const EdgeInsets.symmetric(horizontal: 50),
child: Column( child: Column(
mainAxisSize: MainAxisSize.max, mainAxisSize: MainAxisSize.max,
@ -42,6 +57,7 @@ class LoginView extends StatelessWidget {
controller: emailController, controller: emailController,
textInputType: TextInputType.emailAddress, textInputType: TextInputType.emailAddress,
nextFocusNode: passwordNode, nextFocusNode: passwordNode,
additionalNote: viewModel.messageEmail,
), ),
verticalSpaceSmall, verticalSpaceSmall,
InputField( InputField(
@ -49,6 +65,8 @@ class LoginView extends StatelessWidget {
password: true, password: true,
controller: passwordController, controller: passwordController,
fieldFocusNode: passwordNode, fieldFocusNode: passwordNode,
additionalNote: viewModel.messagePassword,
enterPressed: () => login(viewModel),
), ),
verticalSpaceMedium, verticalSpaceMedium,
Row( Row(
@ -58,21 +76,14 @@ class LoginView extends StatelessWidget {
BusyButton( BusyButton(
title: 'Войти', title: 'Войти',
busy: viewModel.busy, busy: viewModel.busy,
onPressed: () { onPressed: () => login(viewModel),
viewModel.login(
email: emailController.text.trim(),
password: passwordController.text,
);
},
) )
], ],
), ),
verticalSpaceLarge, verticalSpaceLarge,
TextLink( TextLink(
'Регистрация', 'Регистрация',
onPressed: () { onPressed: () {},
//viewModel.navigateToSignUp();
},
) )
], ],
), ),

View File

@ -1,9 +1,74 @@
import 'package:aman_kassa_flutter/core/base/base_view_model.dart'; 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 { class LoginViewModel extends BaseViewModel {
LoginViewModel();
void login({String email, String password}) {} //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 // Add ViewModel specific code here
} }

View File

@ -88,6 +88,13 @@ packages:
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "3.1.0" version: "3.1.0"
google_fonts:
dependency: "direct main"
description:
name: google_fonts
url: "https://pub.dartlang.org"
source: hosted
version: "1.1.0"
http: http:
dependency: "direct main" dependency: "direct main"
description: description:
@ -151,6 +158,27 @@ packages:
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "1.6.4" version: "1.6.4"
path_provider:
dependency: transitive
description:
name: path_provider
url: "https://pub.dartlang.org"
source: hosted
version: "1.6.9"
path_provider_macos:
dependency: transitive
description:
name: path_provider_macos
url: "https://pub.dartlang.org"
source: hosted
version: "0.0.4+3"
path_provider_platform_interface:
dependency: transitive
description:
name: path_provider_platform_interface
url: "https://pub.dartlang.org"
source: hosted
version: "1.0.2"
pedantic: pedantic:
dependency: transitive dependency: transitive
description: description:
@ -165,6 +193,20 @@ packages:
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "2.4.0" version: "2.4.0"
platform:
dependency: transitive
description:
name: platform
url: "https://pub.dartlang.org"
source: hosted
version: "2.2.1"
plugin_platform_interface:
dependency: transitive
description:
name: plugin_platform_interface
url: "https://pub.dartlang.org"
source: hosted
version: "1.0.2"
provider: provider:
dependency: "direct main" dependency: "direct main"
description: description:
@ -270,4 +312,4 @@ packages:
version: "3.6.1" version: "3.6.1"
sdks: sdks:
dart: ">=2.7.0 <3.0.0" dart: ">=2.7.0 <3.0.0"
flutter: ">=1.16.0" flutter: ">=1.17.0 <2.0.0"

View File

@ -15,6 +15,7 @@ dependencies:
get_it: ^3.0.3 get_it: ^3.0.3
equatable: ^1.1.1 equatable: ^1.1.1
http: ^0.12.1 http: ^0.12.1
google_fonts: ^1.1.0
dev_dependencies: dev_dependencies:
flutter_test: flutter_test:
sdk: flutter sdk: flutter