From 3e7007ab63fdc0d880f5550752340411c941fb42 Mon Sep 17 00:00:00 2001 From: "Serik.Uvaissov" Date: Tue, 26 May 2020 20:32:41 +0600 Subject: [PATCH] floating action and bottom bar release --- lib/core/locator.dart | 4 +- lib/core/logger.dart | 81 +++++++++------- lib/core/models/user.dart | 34 +++---- lib/core/services/ApiService.dart | 78 +++++++-------- lib/core/services/authentication_service.dart | 42 ++++---- lib/main.dart | 13 +++ lib/views/home/home_view.dart | 96 ++++++++++++++++++- lib/views/home/home_view_model.dart | 36 +++++-- lib/views/login/login_view.dart | 39 +++++--- lib/views/login/login_view_model.dart | 69 ++++++++++++- pubspec.lock | 44 ++++++++- pubspec.yaml | 3 +- 12 files changed, 388 insertions(+), 151 deletions(-) diff --git a/lib/core/locator.dart b/lib/core/locator.dart index 00cb325..09e011e 100644 --- a/lib/core/locator.dart +++ b/lib/core/locator.dart @@ -1,7 +1,7 @@ import '../core/services/ApiService.dart'; -import '../core/services/authentication_service.dart'; +import '../core/services/dialog_service.dart'; import '../core/logger.dart'; import '../core/services/navigator_service.dart'; import 'package:get_it/get_it.dart'; @@ -17,6 +17,8 @@ class LocatorInjector { locator.registerLazySingleton(() => ApiService()); _log.d('Initializing Navigator Service'); locator.registerLazySingleton(() => NavigatorService()); + _log.d('Initializing Dialog Service'); + locator.registerLazySingleton(() => DialogService()); } } \ No newline at end of file diff --git a/lib/core/logger.dart b/lib/core/logger.dart index 620f8fc..1065a6d 100644 --- a/lib/core/logger.dart +++ b/lib/core/logger.dart @@ -1,43 +1,52 @@ -import 'dart:developer' as prefix0; +//import 'dart:developer' as prefix0; import 'package:logger/logger.dart'; -class SimpleLogPrinter extends LogPrinter { - static int counter = 0; - final String className; +// class SimpleLogPrinter extends LogPrinter { +// static int counter = 0; +// final String className; - SimpleLogPrinter(this.className); +// SimpleLogPrinter(this.className); - @override - List log(LogEvent event) { - prefix0.log( - event.message, - time: DateTime.now(), - level: () { - switch (event.level) { - case Level.verbose: - return 0; - case Level.debug: - return 500; - case Level.info: - return 0; - case Level.warning: - return 1500; - case Level.error: - return 2000; - case Level.wtf: - return 2000; - default: - return 2000; - } - }(), - name: className, - error: event.error, - sequenceNumber: counter += 1, - ); - return []; - } -} +// @override +// List log(LogEvent event) { +// prefix0.log( +// event.message, +// time: DateTime.now(), +// level: () { +// switch (event.level) { +// case Level.verbose: +// return 0; +// case Level.debug: +// return 500; +// case Level.info: +// return 0; +// case Level.warning: +// return 1500; +// case Level.error: +// return 2000; +// case Level.wtf: +// return 2000; +// default: +// return 2000; +// } +// }(), +// name: className, +// error: event.error, +// sequenceNumber: counter += 1, +// ); +// return []; +// } +// } 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 + )); } \ No newline at end of file diff --git a/lib/core/models/user.dart b/lib/core/models/user.dart index 5baa452..6ed4a42 100644 --- a/lib/core/models/user.dart +++ b/lib/core/models/user.dart @@ -1,20 +1,22 @@ class User { - final String token; - final String fullName; + + final String name; final String email; + final String fullName; + final String token; + int appCompanyId; + int kassaId; + + User({this.email, this.fullName, this.name, this.token, this.appCompanyId, this.kassaId}); - User({this.token, this.fullName, this.email}); - - User.fromData(Map data) - : token = data['api_token'], - fullName = data['fullName'], - email = data['email']; - - Map toJson() { - return { - 'api_token': token, - 'fullName': fullName, - 'email': email, - }; - } + factory User.fromJson(Map json) { + return User ( + name: json['name'], + email: json['mail'], + token: json['api_token'], + fullName: json['fullname'], + appCompanyId: json['app_company_id'] as int, + kassaId: json['kassa_id'] as int, + ); + } } diff --git a/lib/core/services/ApiService.dart b/lib/core/services/ApiService.dart index e8ef183..0e586d7 100644 --- a/lib/core/services/ApiService.dart +++ b/lib/core/services/ApiService.dart @@ -3,61 +3,49 @@ import 'dart:io'; import 'package:aman_kassa_flutter/core/base/base_service.dart'; import 'package:aman_kassa_flutter/core/models/session.dart'; +import '../models/authResponse.dart'; + import 'package:http/http.dart' as http; /// The service responsible for networking requests class ApiService extends BaseService { static const endpoint = 'https://kassa-test.aman.com.kz/ru/api/v2'; - + var client = new http.Client(); - - - Future isActive(String token) async { - // var map = new Map(); - // map['api_token'] = token; - // var response = await client.post( - // '$endpoint/test_auth', - // headers: { - // HttpHeaders.contentTypeHeader: "multipart/form-data", - // HttpHeaders.cacheControlHeader: "no-cache" - // }, - // body: map); - // print(response.body); - // return Session.fromData(token,json.decode(response.body)); - Map requestBody = { - 'api_token':token - }; - Map headers= { - 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 authenticate(String email, String password) async { + Map requestBody = { + 'email': email, + 'password': password + }; + 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> getPostsForUser(int userId) async { - // var posts = List(); - // // Get user posts for id - // var response = await client.get('$endpoint/posts?userId=$userId'); + Future isActive(String token) async { + Map requestBody = {'api_token': token}; + var response = await requestFormData('/test_auth', requestBody); + final respStr = await response.stream.bytesToString(); + return Session.fromData(token, json.decode(respStr)['body']); + } - // // parse into List - // var parsed = json.decode(response.body) as List; + Future requestFormData( + String point, Map requestBody) async { + Map headers = { + HttpHeaders.contentTypeHeader: "multipart/form-data", + HttpHeaders.cacheControlHeader: "no-cache" + }; - // // loop and convert each item to Post - // for (var post in parsed) { - // posts.add(Post.fromJson(post)); - // } + var uri = Uri.parse('$endpoint$point'); + var request = http.MultipartRequest('POST', uri) + ..headers.addAll( + headers) //if u have headers, basic auth, token bearer... Else remove line + ..fields.addAll(requestBody); + return await request.send(); + } - // return posts; - // } - -} \ No newline at end of file +} diff --git a/lib/core/services/authentication_service.dart b/lib/core/services/authentication_service.dart index 1170127..c174173 100644 --- a/lib/core/services/authentication_service.dart +++ b/lib/core/services/authentication_service.dart @@ -1,13 +1,12 @@ - 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/user.dart'; +import 'package:aman_kassa_flutter/core/models/authResponse.dart'; import 'package:flutter/foundation.dart'; import 'ApiService.dart'; class AuthenticationService extends BaseService { - final ApiService _api; AuthenticationService({ApiService api}) : _api = api; @@ -18,31 +17,28 @@ class AuthenticationService extends BaseService { Session _session; Session get currentSession => _session; - // Future loginWithEmail({ - // @required String email, - // @required String password, - // }) async { - // try { - // User result = await _api.getUserProfile(123); - // _currentUser = result; - // return result != null; - // } catch (e) { - // return e.message; - // } - // } + Future loginWithEmail({ + @required String email, + @required String password, + }) async { + try { + AuthBody result = await _api.authenticate(email, password); + if (result.user != null) { + _currentUser = result.user; + } + return result; + } catch (e) { + print(e); + return null; + } + } - Future isUserLoggedIn(token) async { + Future isUserLoggedIn(String token) async { Session session = await _api.isActive(token); - if("OK" == session.message){ + if ("OK" == session.message) { _session = session; return true; } - return false; + return false; } - - // Future isUserLoggedIn() async { - // var user = await _firebaseAuth.currentUser(); - // await _populateCurrentUser(user); - // return user != null; - // } } diff --git a/lib/main.dart b/lib/main.dart index 5580db9..19f07fe 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -6,6 +6,8 @@ import 'core/locator.dart'; import 'core/providers.dart'; import 'core/router.dart'; import 'core/services/navigator_service.dart'; +import 'core/services/dialog_service.dart'; +import './widgets/dialog_manager.dart'; //pages import 'views/start_up/start_up_view.dart'; @@ -24,6 +26,17 @@ class MainApplication extends StatelessWidget { return MultiProvider( providers: ProviderInjector.providers.toList(), child: MaterialApp( + theme: ThemeData( + //primaryColor: blueColor, + backgroundColor: Colors.white, + scaffoldBackgroundColor: Colors.white, + ), + debugShowCheckedModeBanner: false, + builder: (context, child) => Navigator( + key: locator().dialogNavigationKey, + onGenerateRoute: (settings) => MaterialPageRoute( + builder: (context) => DialogManager(child: child)), + ), navigatorKey: locator().navigatorKey, home: StartUpView(), // first page onGenerateRoute: generateRoute, diff --git a/lib/views/home/home_view.dart b/lib/views/home/home_view.dart index 532f47d..1d920b6 100644 --- a/lib/views/home/home_view.dart +++ b/lib/views/home/home_view.dart @@ -1,22 +1,110 @@ library home_view; import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; import 'package:stacked/stacked.dart'; import 'home_view_model.dart'; class HomeView extends StatelessWidget { + @override Widget build(BuildContext context) { return ViewModelBuilder.reactive( - viewModelBuilder: () => HomeViewModel(), + viewModelBuilder: () => HomeViewModel( + authenticationService: Provider.of(context), + navigationService: Provider.of(context)), onModelReady: (viewModel) { - viewModel.busy = true; + viewModel.initialize(); + viewModel.pageController = new PageController(initialPage: viewModel.tabIndex); }, builder: (context, viewModel, child) { return Scaffold( - body: Center(child: Text('HomeView')), + body: PageView( + onPageChanged: (index) { + viewModel.tabIndex = index; + }, + controller: viewModel.pageController, + children: [ + 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: [ + 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: [ + Text('PrefencesTab index:$index ${viewModel.currentUser.fullName} ') + ], + ), + ); + } } diff --git a/lib/views/home/home_view_model.dart b/lib/views/home/home_view_model.dart index 3b15306..ec6ed2a 100644 --- a/lib/views/home/home_view_model.dart +++ b/lib/views/home/home_view_model.dart @@ -1,22 +1,42 @@ 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/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:flutter/material.dart'; class HomeViewModel extends BaseViewModel { - final NavigatorService _navigationService = locator(); - int _counter; + NavigatorService _navigationService; + AuthenticationService _authenticationService; + final DialogService _dialogService = locator(); - HomeViewModel({int counter = 0}) : this._counter = counter; + User _currentUser ; + User get currentUser => _currentUser; - int get counter => this._counter; - set counter(int value) { - this._counter = value; + HomeViewModel({ + @required AuthenticationService authenticationService, + @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(); } - void increment() => this.counter += 1; + void initialize() { + _currentUser = _authenticationService.currentUser; + } } \ No newline at end of file diff --git a/lib/views/login/login_view.dart b/lib/views/login/login_view.dart index 5728734..fc80cb9 100644 --- a/lib/views/login/login_view.dart +++ b/lib/views/login/login_view.dart @@ -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/input_field.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:provider/provider.dart'; import 'package:stacked/stacked.dart'; import 'login_view_model.dart'; class LoginView extends StatelessWidget { - final emailController = TextEditingController(); - final passwordController = TextEditingController(); + final emailController = TextEditingController(text: 'test@kkm-kassa.kz'); + final passwordController = TextEditingController(text: 'qwe123'); final FocusNode passwordNode = new FocusNode(); + final GlobalKey _scaffoldKey = new GlobalKey(); @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(),))); + } + } + //LoginViewModel viewModel = LoginViewModel(); return ViewModelBuilder.reactive( - viewModelBuilder: () => LoginViewModel(), + viewModelBuilder: () => LoginViewModel( + authenticationService: Provider.of(context), + navigationService: Provider.of(context)), onModelReady: (viewModel) { // Do something once your viewModel is initialized }, builder: (context, viewModel, child) { return Scaffold( - //backgroundColor: Colors.white, - body: Padding( + key: _scaffoldKey, + //backgroundColor: Colors.white, + body: Padding( padding: const EdgeInsets.symmetric(horizontal: 50), child: Column( mainAxisSize: MainAxisSize.max, @@ -42,6 +57,7 @@ class LoginView extends StatelessWidget { controller: emailController, textInputType: TextInputType.emailAddress, nextFocusNode: passwordNode, + additionalNote: viewModel.messageEmail, ), verticalSpaceSmall, InputField( @@ -49,6 +65,8 @@ class LoginView extends StatelessWidget { password: true, controller: passwordController, fieldFocusNode: passwordNode, + additionalNote: viewModel.messagePassword, + enterPressed: () => login(viewModel), ), verticalSpaceMedium, Row( @@ -58,21 +76,14 @@ class LoginView extends StatelessWidget { BusyButton( title: 'Войти', busy: viewModel.busy, - onPressed: () { - viewModel.login( - email: emailController.text.trim(), - password: passwordController.text, - ); - }, + onPressed: () => login(viewModel), ) ], ), verticalSpaceLarge, TextLink( 'Регистрация', - onPressed: () { - //viewModel.navigateToSignUp(); - }, + onPressed: () {}, ) ], ), diff --git a/lib/views/login/login_view_model.dart b/lib/views/login/login_view_model.dart index a8c0eed..6010e30 100644 --- a/lib/views/login/login_view_model.dart +++ b/lib/views/login/login_view_model.dart @@ -1,9 +1,74 @@ 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 { - 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 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 } \ No newline at end of file diff --git a/pubspec.lock b/pubspec.lock index 9caeade..31df060 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -88,6 +88,13 @@ packages: url: "https://pub.dartlang.org" source: hosted 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: dependency: "direct main" description: @@ -151,6 +158,27 @@ packages: url: "https://pub.dartlang.org" source: hosted 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: dependency: transitive description: @@ -165,6 +193,20 @@ packages: url: "https://pub.dartlang.org" source: hosted 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: dependency: "direct main" description: @@ -270,4 +312,4 @@ packages: version: "3.6.1" sdks: dart: ">=2.7.0 <3.0.0" - flutter: ">=1.16.0" + flutter: ">=1.17.0 <2.0.0" diff --git a/pubspec.yaml b/pubspec.yaml index 9d452e8..1a6dd00 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -14,7 +14,8 @@ dependencies: logger: ^0.9.1 get_it: ^3.0.3 equatable: ^1.1.1 - http: ^0.12.1 + http: ^0.12.1 + google_fonts: ^1.1.0 dev_dependencies: flutter_test: sdk: flutter