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/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>(() => ApiService());
_log.d('Initializing Navigator Service');
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';
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<String> 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<String> 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
));
}

View File

@ -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<String, dynamic> data)
: token = data['api_token'],
fullName = data['fullName'],
email = data['email'];
Map<String, dynamic> toJson() {
return {
'api_token': token,
'fullName': fullName,
'email': email,
};
}
factory User.fromJson(Map<String, dynamic> 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,
);
}
}

View File

@ -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<Session> isActive(String token) async {
// var map = new Map<String, dynamic>();
// 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<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<AuthBody> authenticate(String email, String password) async {
Map<String, String> requestBody = <String, String>{
'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<List<Post>> getPostsForUser(int userId) async {
// var posts = List<Post>();
// // Get user posts for id
// var response = await client.get('$endpoint/posts?userId=$userId');
Future<Session> 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']);
}
// // parse into List
// var parsed = json.decode(response.body) as List<dynamic>;
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"
};
// // 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;
// }
}
}

View File

@ -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<AuthBody> 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<bool> isUserLoggedIn(token) async {
Future<bool> 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<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/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<DialogService>().dialogNavigationKey,
onGenerateRoute: (settings) => MaterialPageRoute(
builder: (context) => DialogManager(child: child)),
),
navigatorKey: locator<NavigatorService>().navigatorKey,
home: StartUpView(), // first page
onGenerateRoute: generateRoute,

View File

@ -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<HomeViewModel>.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: <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/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<NavigatorService>();
int _counter;
NavigatorService _navigationService;
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;
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;
}
}

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/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<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(),)));
}
}
//LoginViewModel viewModel = LoginViewModel();
return ViewModelBuilder<LoginViewModel>.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: () {},
)
],
),

View File

@ -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<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
}

View File

@ -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"

View File

@ -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