From 46302aed182836bfc1f8ff45f4489d54867315e8 Mon Sep 17 00:00:00 2001 From: "Serik.Uvaissov" Date: Thu, 21 May 2020 16:12:32 +0600 Subject: [PATCH] login navigate --- lib/core/locator.dart | 13 +- lib/core/models/session.dart | 16 +++ lib/core/models/user.dart | 13 +- lib/core/services/ApiService.dart | 40 +++++- lib/core/services/authentication_service.dart | 33 +++-- lib/core/services/navigator_service.dart | 13 ++ lib/main.dart | 17 ++- lib/shared/app_colors.dart | 14 ++ lib/shared/shared_styles.dart | 32 +++++ lib/shared/ui_helpers.dart | 38 +++++ lib/views/home/home_view.dart | 27 +--- lib/views/home/home_view_model.dart | 9 +- lib/views/login/login_view.dart | 64 ++++++++- lib/views/login/login_view_model.dart | 2 + lib/views/start_up/start_up_view.dart | 39 +++++ lib/views/start_up/start_up_view_model.dart | 33 +++++ lib/widgets/fields/busy_button.dart | 52 +++++++ lib/widgets/fields/input_field.dart | 135 ++++++++++++++++++ lib/widgets/fields/note_text.dart | 23 +++ lib/widgets/fields/text_link.dart | 19 +++ 20 files changed, 565 insertions(+), 67 deletions(-) create mode 100644 lib/core/models/session.dart create mode 100644 lib/shared/app_colors.dart create mode 100644 lib/shared/shared_styles.dart create mode 100644 lib/shared/ui_helpers.dart create mode 100644 lib/views/start_up/start_up_view.dart create mode 100644 lib/views/start_up/start_up_view_model.dart create mode 100644 lib/widgets/fields/busy_button.dart create mode 100644 lib/widgets/fields/input_field.dart create mode 100644 lib/widgets/fields/note_text.dart create mode 100644 lib/widgets/fields/text_link.dart diff --git a/lib/core/locator.dart b/lib/core/locator.dart index fba2128..00cb325 100644 --- a/lib/core/locator.dart +++ b/lib/core/locator.dart @@ -1,19 +1,22 @@ -import '../core/services/ApiService.dart'; + +import '../core/services/ApiService.dart'; +import '../core/services/authentication_service.dart'; import '../core/logger.dart'; import '../core/services/navigator_service.dart'; import 'package:get_it/get_it.dart'; import 'package:logger/logger.dart'; -GetIt locator = GetIt.instance; +GetIt locator = GetIt.I; class LocatorInjector { static Logger _log = getLogger('LocatorInjector'); static Future setupLocator() async { - _log.d('Initializing Navigator Service'); - locator.registerLazySingleton(() => NavigatorService()); _log.d('Initializing Api Service'); - locator.registerLazySingleton(() => ApiService()); + locator.registerLazySingleton(() => ApiService()); + _log.d('Initializing Navigator Service'); + locator.registerLazySingleton(() => NavigatorService()); + } } \ No newline at end of file diff --git a/lib/core/models/session.dart b/lib/core/models/session.dart new file mode 100644 index 0000000..d477415 --- /dev/null +++ b/lib/core/models/session.dart @@ -0,0 +1,16 @@ +class Session { + String token; + int appCompanyId; + int kassaId; + int userId; + String message; + Session(); + + + Session.fromData(String token ,Map data) + : token = token, + appCompanyId = data['app_company_id'], + userId = data['user_id'], + message = data['message'], + kassaId = data['kassa_id']; +} \ No newline at end of file diff --git a/lib/core/models/user.dart b/lib/core/models/user.dart index b632465..5baa452 100644 --- a/lib/core/models/user.dart +++ b/lib/core/models/user.dart @@ -1,23 +1,20 @@ class User { - final String id; + final String token; final String fullName; final String email; - final String userRole; - User({this.id, this.fullName, this.email, this.userRole}); + User({this.token, this.fullName, this.email}); User.fromData(Map data) - : id = data['id'], + : token = data['api_token'], fullName = data['fullName'], - email = data['email'], - userRole = data['userRole']; + email = data['email']; Map toJson() { return { - 'id': id, + 'api_token': token, 'fullName': fullName, 'email': email, - 'userRole': userRole, }; } } diff --git a/lib/core/services/ApiService.dart b/lib/core/services/ApiService.dart index 43b5e32..e8ef183 100644 --- a/lib/core/services/ApiService.dart +++ b/lib/core/services/ApiService.dart @@ -1,21 +1,47 @@ import 'dart:convert'; +import 'dart:io'; import 'package:aman_kassa_flutter/core/base/base_service.dart'; -import 'package:aman_kassa_flutter/core/models/user.dart'; +import 'package:aman_kassa_flutter/core/models/session.dart'; + import 'package:http/http.dart' as http; /// The service responsible for networking requests class ApiService extends BaseService { - static const endpoint = 'https://jsonplaceholder.typicode.com'; + static const endpoint = 'https://kassa-test.aman.com.kz/ru/api/v2'; var client = new http.Client(); + + - Future getUserProfile(int userId) async { - // Get user profile for id - var response = await client.get('$endpoint/users/$userId'); + 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" + }; - // Convert and return - return User.fromData(json.decode(response.body)); + 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> getPostsForUser(int userId) async { diff --git a/lib/core/services/authentication_service.dart b/lib/core/services/authentication_service.dart index 2e2063f..1170127 100644 --- a/lib/core/services/authentication_service.dart +++ b/lib/core/services/authentication_service.dart @@ -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/user.dart'; import 'package:flutter/foundation.dart'; @@ -14,17 +15,29 @@ class AuthenticationService extends BaseService { User _currentUser; User get currentUser => _currentUser; - 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; + 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 isUserLoggedIn(token) async { + Session session = await _api.isActive(token); + if("OK" == session.message){ + _session = session; + return true; } + return false; } // Future isUserLoggedIn() async { diff --git a/lib/core/services/navigator_service.dart b/lib/core/services/navigator_service.dart index 7e94494..bc07b14 100644 --- a/lib/core/services/navigator_service.dart +++ b/lib/core/services/navigator_service.dart @@ -4,6 +4,19 @@ import 'package:flutter/material.dart'; class NavigatorService extends BaseService { final GlobalKey navigatorKey = GlobalKey(); + Future push(String routeName, {dynamic arguments}) { + log.i('routeName: $routeName'); + return navigatorKey.currentState + .pushNamed(routeName, arguments: arguments); + } + + Future replace(String routeName) { + log.i('routeName: $routeName'); + return navigatorKey.currentState + .pushNamedAndRemoveUntil(routeName, (Route route) => false); + } + + Future navigateToPage(MaterialPageRoute pageRoute) async { log.i('navigateToPage: pageRoute: ${pageRoute.settings.name}'); if (navigatorKey.currentState == null) { diff --git a/lib/main.dart b/lib/main.dart index 881541a..5580db9 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -1,14 +1,19 @@ -import 'package:aman_kassa_flutter/views/login/login_view.dart'; - +//general +import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; +//service & tools import 'core/locator.dart'; import 'core/providers.dart'; import 'core/router.dart'; import 'core/services/navigator_service.dart'; -import 'package:flutter/material.dart'; -import 'package:provider/provider.dart'; -import 'views/home/home_view.dart'; +//pages +import 'views/start_up/start_up_view.dart'; + +//main start void main() async { + WidgetsFlutterBinding.ensureInitialized(); + //initialize locator await LocatorInjector.setupLocator(); runApp(MainApplication()); } @@ -20,7 +25,7 @@ class MainApplication extends StatelessWidget { providers: ProviderInjector.providers.toList(), child: MaterialApp( navigatorKey: locator().navigatorKey, - home: HomeView(), + home: StartUpView(), // first page onGenerateRoute: generateRoute, ), ); diff --git a/lib/shared/app_colors.dart b/lib/shared/app_colors.dart new file mode 100644 index 0000000..76ee04f --- /dev/null +++ b/lib/shared/app_colors.dart @@ -0,0 +1,14 @@ +import 'package:flutter/material.dart'; + +const Color shadowColor = Color.fromRGBO(80, 137, 196, 0.47); +const Color cardShadowColor = Color.fromRGBO(228, 229, 231, 0.25); +const Color blueColor = Color.fromRGBO(96, 205, 255, 1); +const Color blueColorLigth = Color.fromRGBO(96, 205, 255, 0.536); +const Color redColor = Color.fromRGBO(255, 98, 96, 1); +const Color greenColor = Color.fromRGBO(59, 222, 134, 1); +const Color whiteColor = Color.fromRGBO(255, 255, 255, 1); +const Color textColor = Color.fromRGBO(107, 120, 151, 1); +const Color textColorLight = Color.fromRGBO(162, 171, 191, 1); +const Color dayColor = Color.fromRGBO(52, 72, 94, 0.536); +const Color dayColorLight = Color.fromRGBO(255, 228, 231, 1); +const Color backgroundColor = Color.fromRGBO(249, 250, 254, 1); diff --git a/lib/shared/shared_styles.dart b/lib/shared/shared_styles.dart new file mode 100644 index 0000000..57f7a0e --- /dev/null +++ b/lib/shared/shared_styles.dart @@ -0,0 +1,32 @@ +import 'package:aman_kassa_flutter/shared/app_colors.dart'; +import 'package:flutter/material.dart'; + +// Box Decorations + +BoxDecoration fieldDecortaion = BoxDecoration( + borderRadius: BorderRadius.circular(5), color: Colors.white); + +BoxDecoration disabledFieldDecortaion = BoxDecoration( + borderRadius: BorderRadius.circular(5), color: Colors.grey[100]); + +// Field Variables + +const double fieldHeight = 55; +const double smallFieldHeight = 40; +const double inputFieldBottomMargin = 30; +const double inputFieldSmallBottomMargin = 0; +const EdgeInsets fieldPadding = const EdgeInsets.symmetric(horizontal: 15); +const EdgeInsets largeFieldPadding = + const EdgeInsets.symmetric(horizontal: 15, vertical: 15); + +// Text Variables +const TextStyle buttonTitleTextStyle = + const TextStyle(fontWeight: FontWeight.w400, color: whiteColor, fontSize: 15); + +const TextStyle stepTitleTextStyle = + const TextStyle(fontWeight: FontWeight.w700, color: textColor, fontSize: 15); +const TextStyle stepSubTitleTextStyle = const TextStyle(fontWeight: FontWeight.w400, color: textColor, fontSize: 12); + +// Box Shadow +const BoxShadow mainShadowBox = BoxShadow(blurRadius: 16, color: shadowColor, offset: Offset(0, 5)); +const BoxShadow cardShadowBox = BoxShadow(blurRadius: 23, color: cardShadowColor, offset: Offset(0, 2)); \ No newline at end of file diff --git a/lib/shared/ui_helpers.dart b/lib/shared/ui_helpers.dart new file mode 100644 index 0000000..eb879f4 --- /dev/null +++ b/lib/shared/ui_helpers.dart @@ -0,0 +1,38 @@ +import 'package:flutter/material.dart'; + +const Widget horizontalSpaceTiny = SizedBox(width: 5.0); +const Widget horizontalSpaceSmall = SizedBox(width: 10.0); +const Widget horizontalSpaceMedium = SizedBox(width: 25.0); + +const Widget verticalSpaceTiny = SizedBox(height: 5.0); +const Widget verticalSpaceSmall = SizedBox(height: 10.0); +const Widget verticalSpaceMedium = SizedBox(height: 25.0); +const Widget verticalSpaceLarge = SizedBox(height: 50.0); +const Widget verticalSpaceMassive = SizedBox(height: 120.0); + +Widget spacedDivider = Column( + children: const [ + verticalSpaceMedium, + const Divider(color: Colors.blueGrey, height: 5.0), + verticalSpaceMedium, + ], +); + +Widget verticalSpace(double height) => SizedBox(height: height); + +double screenWidth(BuildContext context) => MediaQuery.of(context).size.width; +double screenHeight(BuildContext context) => MediaQuery.of(context).size.height; + +double screenHeightFraction(BuildContext context, + {int dividedBy = 1, double offsetBy = 0}) => + (screenHeight(context) - offsetBy) / dividedBy; + +double screenWidthFraction(BuildContext context, + {int dividedBy = 1, double offsetBy = 0}) => + (screenWidth(context) - offsetBy) / dividedBy; + +double halfScreenWidth(BuildContext context) => + screenWidthFraction(context, dividedBy: 2); + +double thirdScreenWidth(BuildContext context) => + screenWidthFraction(context, dividedBy: 3); diff --git a/lib/views/home/home_view.dart b/lib/views/home/home_view.dart index 122697a..532f47d 100644 --- a/lib/views/home/home_view.dart +++ b/lib/views/home/home_view.dart @@ -10,32 +10,13 @@ class HomeView extends StatelessWidget { return ViewModelBuilder.reactive( viewModelBuilder: () => HomeViewModel(), onModelReady: (viewModel) { - //viewModel.busy = true; + viewModel.busy = true; }, builder: (context, viewModel, child) { - return buildWaitingLogo(context, viewModel, child); + return Scaffold( + body: Center(child: Text('HomeView')), + ); }); } - Widget buildWaitingLogo( - BuildContext context, HomeViewModel viewModel, Widget child) => - new Scaffold( - body: Center( - child: Column( - mainAxisSize: MainAxisSize.min, - children: [ - SizedBox( - width: 300, - height: 100, - child: Image.asset('assets/images/icon_large.png'), - ), - CircularProgressIndicator( - strokeWidth: 3, - valueColor: AlwaysStoppedAnimation( - Colors.yellow[300], - ), - ) - ], - ), - )); } diff --git a/lib/views/home/home_view_model.dart b/lib/views/home/home_view_model.dart index 4a6710d..3b15306 100644 --- a/lib/views/home/home_view_model.dart +++ b/lib/views/home/home_view_model.dart @@ -1,9 +1,8 @@ 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/route_names.dart'; + import 'package:aman_kassa_flutter/core/services/navigator_service.dart'; -import 'package:aman_kassa_flutter/views/login/login_view.dart'; -import 'package:flutter/material.dart'; + class HomeViewModel extends BaseViewModel { final NavigatorService _navigationService = locator(); @@ -19,7 +18,5 @@ class HomeViewModel extends BaseViewModel { void increment() => this.counter += 1; - void goToLogin() { - _navigationService.navigateToPage(MaterialPageRoute(builder: (context) => LoginView())); - } + } \ No newline at end of file diff --git a/lib/views/login/login_view.dart b/lib/views/login/login_view.dart index 6545751..5728734 100644 --- a/lib/views/login/login_view.dart +++ b/lib/views/login/login_view.dart @@ -1,10 +1,19 @@ library login_view; +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:flutter/material.dart'; import 'package:stacked/stacked.dart'; import 'login_view_model.dart'; class LoginView extends StatelessWidget { + final emailController = TextEditingController(); + final passwordController = TextEditingController(); + + final FocusNode passwordNode = new FocusNode(); + @override Widget build(BuildContext context) { //LoginViewModel viewModel = LoginViewModel(); @@ -15,8 +24,59 @@ class LoginView extends StatelessWidget { }, builder: (context, viewModel, child) { return Scaffold( - body: Center(child: Text('LoginMobile')), - ); + //backgroundColor: Colors.white, + body: Padding( + padding: const EdgeInsets.symmetric(horizontal: 50), + child: Column( + mainAxisSize: MainAxisSize.max, + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + SizedBox( + height: 150, + child: Image.asset('assets/images/logo.png'), + //child: FlutterLogo(size: 120,), + ), + InputField( + placeholder: 'Электронная почта', + controller: emailController, + textInputType: TextInputType.emailAddress, + nextFocusNode: passwordNode, + ), + verticalSpaceSmall, + InputField( + placeholder: 'Пароль', + password: true, + controller: passwordController, + fieldFocusNode: passwordNode, + ), + verticalSpaceMedium, + Row( + mainAxisSize: MainAxisSize.max, + mainAxisAlignment: MainAxisAlignment.end, + children: [ + BusyButton( + title: 'Войти', + busy: viewModel.busy, + onPressed: () { + viewModel.login( + email: emailController.text.trim(), + password: passwordController.text, + ); + }, + ) + ], + ), + verticalSpaceLarge, + TextLink( + 'Регистрация', + onPressed: () { + //viewModel.navigateToSignUp(); + }, + ) + ], + ), + )); }); } } diff --git a/lib/views/login/login_view_model.dart b/lib/views/login/login_view_model.dart index 087f76d..a8c0eed 100644 --- a/lib/views/login/login_view_model.dart +++ b/lib/views/login/login_view_model.dart @@ -2,6 +2,8 @@ import 'package:aman_kassa_flutter/core/base/base_view_model.dart'; class LoginViewModel extends BaseViewModel { LoginViewModel(); + + void login({String email, String password}) {} // Add ViewModel specific code here } \ No newline at end of file diff --git a/lib/views/start_up/start_up_view.dart b/lib/views/start_up/start_up_view.dart new file mode 100644 index 0000000..697614a --- /dev/null +++ b/lib/views/start_up/start_up_view.dart @@ -0,0 +1,39 @@ +library home_view; + +import 'package:provider/provider.dart'; + +import 'start_up_view_model.dart'; +import 'package:flutter/material.dart'; +import 'package:stacked/stacked.dart'; + +class StartUpView extends StatelessWidget { + @override + Widget build(BuildContext context) { + return ViewModelBuilder.reactive( + viewModelBuilder: () => StartUpViewModel(authenticationService: Provider.of(context), navigationService: Provider.of(context)), + onModelReady: (viewModel) { + viewModel.handleStartUpLogic(); + }, + builder: (context, viewModel, child) { + return Scaffold( + body: Center( + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + SizedBox( + width: 500, + height: 200, + child: Image.asset('assets/images/icon_large.png'), + ), + CircularProgressIndicator( + strokeWidth: 3, + valueColor: AlwaysStoppedAnimation( + Colors.yellow[300], + ), + ) + ], + ), + )); + }); + } +} diff --git a/lib/views/start_up/start_up_view_model.dart b/lib/views/start_up/start_up_view_model.dart new file mode 100644 index 0000000..993c415 --- /dev/null +++ b/lib/views/start_up/start_up_view_model.dart @@ -0,0 +1,33 @@ +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); + } + } +} \ No newline at end of file diff --git a/lib/widgets/fields/busy_button.dart b/lib/widgets/fields/busy_button.dart new file mode 100644 index 0000000..f5705d2 --- /dev/null +++ b/lib/widgets/fields/busy_button.dart @@ -0,0 +1,52 @@ +import 'package:aman_kassa_flutter/shared/app_colors.dart'; +import 'package:aman_kassa_flutter/shared/shared_styles.dart'; +import 'package:flutter/material.dart'; + +/// A button that shows a busy indicator in place of title +class BusyButton extends StatefulWidget { + final bool busy; + final String title; + final Function onPressed; + final bool enabled; + const BusyButton( + {@required this.title, + this.busy = false, + @required this.onPressed, + this.enabled = true}); + + @override + _BusyButtonState createState() => _BusyButtonState(); +} + +class _BusyButtonState extends State { + @override + Widget build(BuildContext context) { + return GestureDetector( + onTap: widget.onPressed, + child: InkWell( + child: AnimatedContainer( + height: widget.busy ? 40 : null, + width: widget.busy ? 40 : null, + duration: const Duration(milliseconds: 300), + alignment: Alignment.center, + padding: EdgeInsets.symmetric( + horizontal: widget.busy ? 10 : 25, + vertical: widget.busy ? 10 : 15), + decoration: BoxDecoration( + color: widget.enabled ? blueColor : blueColorLigth, + borderRadius: BorderRadius.circular(7), + boxShadow: [mainShadowBox] + ), + child: !widget.busy + ? Text( + widget.title, + style: buttonTitleTextStyle, + ) + : CircularProgressIndicator( + strokeWidth: 2, + valueColor: AlwaysStoppedAnimation(Colors.white)), + ), + ), + ); + } +} diff --git a/lib/widgets/fields/input_field.dart b/lib/widgets/fields/input_field.dart new file mode 100644 index 0000000..b1ae4ef --- /dev/null +++ b/lib/widgets/fields/input_field.dart @@ -0,0 +1,135 @@ +import 'package:aman_kassa_flutter/shared/app_colors.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; +import 'package:aman_kassa_flutter/shared/shared_styles.dart'; +import 'package:aman_kassa_flutter/shared/ui_helpers.dart'; + +import 'note_text.dart'; + +class InputField extends StatefulWidget { + final TextEditingController controller; + final TextInputType textInputType; + final bool password; + final bool isReadOnly; + final String placeholder; + final String validationMessage; + final Function enterPressed; + final bool smallVersion; + final FocusNode fieldFocusNode; + final FocusNode nextFocusNode; + final TextInputAction textInputAction; + final bool multiline; + final String additionalNote; + final Function(String) onChanged; + final TextInputFormatter formatter; + final String initialValue; + final String labelText; + + InputField( + { + this.controller, + @required this.placeholder, + this.enterPressed, + this.fieldFocusNode, + this.nextFocusNode, + this.additionalNote, + this.onChanged, + this.formatter, + this.initialValue, + this.validationMessage, + this.textInputAction = TextInputAction.next, + this.textInputType = TextInputType.text, + this.password = false, + this.isReadOnly = false, + this.multiline = false, + this.smallVersion = false, this.labelText}); + + @override + _InputFieldState createState() => _InputFieldState(); +} + +class _InputFieldState extends State { + bool isPassword; + double fieldHeight = 55; + + @override + void initState() { + super.initState(); + isPassword = widget.password; + } + + @override + Widget build(BuildContext context) { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + if (widget.labelText != null) NoteText(widget.labelText), + Container( + //height: widget.smallVersion ? 40 : fieldHeight, + constraints: BoxConstraints(minHeight: widget.smallVersion ? 40 : fieldHeight), + alignment: Alignment.centerLeft, + padding: fieldPadding, + decoration: + widget.isReadOnly ? disabledFieldDecortaion : fieldDecortaion, + child: Row( + children: [ + Expanded( + child: TextFormField( + style: TextStyle( color: textColor ), + controller: widget.controller, + keyboardType: widget.textInputType, + focusNode: widget.fieldFocusNode, + textInputAction: widget.textInputAction, + maxLines: widget.multiline ? null : 1, + onChanged: widget.onChanged, + initialValue: widget.initialValue, + inputFormatters: + widget.formatter != null ? [widget.formatter] : null, + onEditingComplete: () { + if (widget.enterPressed != null) { + FocusScope.of(context).requestFocus(FocusNode()); + widget.enterPressed(); + } + }, + onFieldSubmitted: (value) { + if (widget.nextFocusNode != null) { + widget.nextFocusNode.requestFocus(); + } + }, + obscureText: isPassword, + readOnly: widget.isReadOnly, + decoration: InputDecoration.collapsed( + hintText: widget.placeholder, + hintStyle: + TextStyle(fontSize: widget.smallVersion ? 12 : 15, color: textColorLight)), + ), + ), + GestureDetector( + onTap: () => setState(() { + isPassword = !isPassword; + }), + child: widget.password + ? Container( + width: fieldHeight, + height: fieldHeight, + alignment: Alignment.center, + child: Icon(isPassword + ? Icons.visibility + : Icons.visibility_off, color: textColor)) + : Container(), + ), + ], + ), + ), + if (widget.validationMessage != null) + NoteText( + widget.validationMessage, + color: Colors.red, + ), + if (widget.additionalNote != null) verticalSpace(5), + if (widget.additionalNote != null) NoteText(widget.additionalNote), + verticalSpaceSmall + ], + ); + } +} diff --git a/lib/widgets/fields/note_text.dart b/lib/widgets/fields/note_text.dart new file mode 100644 index 0000000..a5d093a --- /dev/null +++ b/lib/widgets/fields/note_text.dart @@ -0,0 +1,23 @@ +import 'package:aman_kassa_flutter/shared/app_colors.dart'; +import 'package:flutter/material.dart'; + +class NoteText extends StatelessWidget { + final String text; + final TextAlign textAlign; + final Color color; + final double fontSize; + const NoteText(this.text, {this.textAlign, this.color, this.fontSize}); + + @override + Widget build(BuildContext context) { + return Text( + text, + textAlign: textAlign, + style: TextStyle( + fontSize: fontSize ?? 12, + fontWeight: FontWeight.normal, + color: color ?? dayColor, + ), + ); + } +} diff --git a/lib/widgets/fields/text_link.dart b/lib/widgets/fields/text_link.dart new file mode 100644 index 0000000..22e6e60 --- /dev/null +++ b/lib/widgets/fields/text_link.dart @@ -0,0 +1,19 @@ +import 'package:aman_kassa_flutter/shared/app_colors.dart'; +import 'package:flutter/material.dart'; + +class TextLink extends StatelessWidget { + final String text; + final Function onPressed; + const TextLink(this.text, {this.onPressed}); + + @override + Widget build(BuildContext context) { + return GestureDetector( + onTap: onPressed, + child: Text( + text, + style: TextStyle(fontWeight: FontWeight.w700, fontSize: 14, color: textColor), + ), + ); + } +}