diff --git a/assets/images/bank_layout.jpg b/assets/images/bank_layout.jpg new file mode 100644 index 0000000..ee06ee3 Binary files /dev/null and b/assets/images/bank_layout.jpg differ diff --git a/assets/images/card.png b/assets/images/card.png new file mode 100644 index 0000000..d4351eb Binary files /dev/null and b/assets/images/card.png differ diff --git a/assets/images/phone.png b/assets/images/phone.png new file mode 100644 index 0000000..89c5fce Binary files /dev/null and b/assets/images/phone.png differ diff --git a/assets/images/phone_fit.png b/assets/images/phone_fit.png new file mode 100644 index 0000000..d2baec9 Binary files /dev/null and b/assets/images/phone_fit.png differ diff --git a/lib/core/route_names.dart b/lib/core/route_names.dart index 36abba1..0bd6924 100644 --- a/lib/core/route_names.dart +++ b/lib/core/route_names.dart @@ -2,6 +2,7 @@ const String LoginViewRoute = "LoginView"; const String HomeViewRoute = "HomeView"; const String ImageShowRoute = "ImageShowRoute"; const String PaymentViewRoute = "PaymentView"; +const String PaymentNfcViewRoute = "PaymentNfcViewRoute"; const String HistoryViewRoute = "HistoryView"; const String InfoKkmViewRoute = "InfoKkmViewRoute"; const String QrViewRoute = "QrViewRoute"; diff --git a/lib/core/router.dart b/lib/core/router.dart index 4258764..e47389e 100644 --- a/lib/core/router.dart +++ b/lib/core/router.dart @@ -3,6 +3,7 @@ import 'package:aman_kassa_flutter/views/check/image_show_container.dart'; import 'package:aman_kassa_flutter/views/history/history_view.dart'; import 'package:aman_kassa_flutter/views/info_kkm/info_kkm_view.dart'; import 'package:aman_kassa_flutter/views/payment/payment_view.dart'; +import 'package:aman_kassa_flutter/views/payment_nfc/payment_nfc_view.dart'; import 'package:aman_kassa_flutter/views/qr_view/qr_view.dart'; import './route_names.dart'; @@ -31,6 +32,12 @@ Route generateRoute(RouteSettings settings) { routeName: settings.name, viewToShow: PaymentView(model: model), ); + case PaymentNfcViewRoute: + PaymentModel model = settings.arguments as PaymentModel; + return _getPageRoute( + routeName: settings.name, + viewToShow: PaymentNfcView(model: model), + ); case HistoryViewRoute: return _getPageRoute( routeName: settings.name, diff --git a/lib/main.dart b/lib/main.dart index b94f3ea..9498c87 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -3,6 +3,7 @@ import 'package:flutter_redux/flutter_redux.dart'; import 'package:aman_kassa_flutter/shared/app_colors.dart'; import 'package:flutter/material.dart'; +import 'package:flutter_screenutil/screenutil.dart'; import 'package:google_fonts/google_fonts.dart'; //service & tools import 'package:aman_kassa_flutter/redux/store.dart'; @@ -29,6 +30,7 @@ class MainApplication extends StatelessWidget { @override Widget build(BuildContext context) { + return StoreProvider( store: Redux.store, child: MaterialApp( diff --git a/lib/shared/app_colors.dart b/lib/shared/app_colors.dart index 060bd65..c4580af 100644 --- a/lib/shared/app_colors.dart +++ b/lib/shared/app_colors.dart @@ -12,6 +12,9 @@ const Color greenColor = Color.fromRGBO(92, 184, 92, 1); const Color whiteColor = Color.fromRGBO(255, 255, 255, 1); const Color yellowColor = Color.fromRGBO(250, 175, 0, 1); +const Color purpleColor = Color.fromRGBO(118, 122, 230, 1); +const Color purpleSecondColor = Color.fromRGBO(140, 143, 236, 1); + const Color textColor = Color.fromRGBO(51, 51, 51, 1); diff --git a/lib/views/payment/payment_view.dart b/lib/views/payment/payment_view.dart index 4355b6c..9f61099 100644 --- a/lib/views/payment/payment_view.dart +++ b/lib/views/payment/payment_view.dart @@ -148,6 +148,11 @@ class _PaymentViewState extends State { ], ), ), + Container( + child: IconButton(icon: Icon(Icons.nfc), onPressed: () { + _navigatorService.push(PaymentNfcViewRoute, arguments: widget.model); + }), + ), verticalSpaceLarge, Expanded( child: Container(), diff --git a/lib/views/payment_nfc/payment_nfc_view.dart b/lib/views/payment_nfc/payment_nfc_view.dart new file mode 100644 index 0000000..30aa1d3 --- /dev/null +++ b/lib/views/payment_nfc/payment_nfc_view.dart @@ -0,0 +1,173 @@ +import 'package:aman_kassa_flutter/core/locator.dart'; +import 'package:aman_kassa_flutter/core/models/calc_model.dart'; +import 'package:aman_kassa_flutter/core/models/product_dao.dart'; +import 'package:aman_kassa_flutter/core/models/response.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/dialog_service.dart'; +import 'package:aman_kassa_flutter/core/services/navigator_service.dart'; +import 'package:aman_kassa_flutter/redux/actions/calc_actions.dart'; +import 'package:aman_kassa_flutter/redux/actions/kassa_actions.dart'; +import 'package:aman_kassa_flutter/redux/actions/user_actions.dart'; +import 'package:aman_kassa_flutter/redux/constants/operation_const.dart'; +import 'package:aman_kassa_flutter/redux/constants/setting_const.dart'; +import 'package:aman_kassa_flutter/redux/state/calc_state.dart'; +import 'package:aman_kassa_flutter/redux/state/kassa_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/views/check/image_show_container.dart'; +import 'package:aman_kassa_flutter/views/payment/payment_view.dart'; +import 'package:aman_kassa_flutter/views/payment_nfc/widgets/background_view.dart'; +import 'package:aman_kassa_flutter/views/payment_nfc/widgets/card_view.dart'; +import 'package:aman_kassa_flutter/views/payment_nfc/widgets/phone_view.dart'; +import 'package:aman_kassa_flutter/views/payment_nfc/widgets/text_state.dart'; +import 'package:aman_kassa_flutter/widgets/components/calculator/calculator.dart'; +import 'package:aman_kassa_flutter/widgets/fields/busy_button.dart'; +import 'package:aman_kassa_flutter/widgets/loader/Dialogs.dart'; +import 'package:auto_size_text/auto_size_text.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_redux/flutter_redux.dart'; +import 'package:flutter_screenutil/screenutil.dart'; + +class PaymentNfcView extends StatefulWidget { + final PaymentModel model; + + const PaymentNfcView({Key key, this.model}) : super(key: key); + + @override + _PaymentNfcViewState createState() => _PaymentNfcViewState(); +} + +class _PaymentNfcViewState extends State { + bool isBusy; + bool isPhoneScaled = false; + int status = 0; + + @override + void initState() { + super.initState(); + isBusy = false; + } + + @override + Widget build(BuildContext context) { + return WillPopScope( + onWillPop: () { + if (!isBusy) Navigator.pop(context); + return new Future(() => false); + }, + child: Scaffold( + appBar: AppBar( + brightness: Brightness.light, + backgroundColor: purpleColor, + elevation: 0, + leading: IconButton( + icon: Icon(Icons.arrow_back_ios), + color: whiteColor, + onPressed: () => Navigator.pop(context), + ), + title: Text( + dataTitle(), + style: TextStyle(color: whiteColor), + ), + actions: [ + FlatButton( + onPressed: () { + setState(() { + isPhoneScaled = !isPhoneScaled; + status += 1; + }); + }, + child: Icon(Icons.add)), + ], + ), + body: Container( + decoration: BoxDecoration(color: purpleColor), + padding: EdgeInsets.symmetric( + vertical: ScreenUtil().setSp(12.0), + horizontal: ScreenUtil().setSp(12.0)), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + dataText(), + style: TextStyle( + fontWeight: FontWeight.bold, + color: whiteColor.withOpacity(0.7), + fontSize: ScreenUtil().setSp(15.0)), + ), + buildStoreConnector(), + Expanded( + child: Stack( + children: [ + BackgroundView(), + TextStateView( + status: status, + ), + CardView( + show: isPhoneScaled, + ), + PhoneView(scaled: isPhoneScaled, status: status,), + ], + ), + ) + ], + ), + ), + ), + ); + } + + String dataTitle() => + widget.model.operationType == OperationTypePay ? 'Оплата' : 'Возврат'; + + String dataText() => widget.model.operationType == OperationTypePay + ? 'К оплате' + : 'К возврату'; + + StoreConnector buildStoreConnector() { + if (widget.model.mode == SettingModeCalc) { + return StoreConnector( + converter: (store) => store.state.calcState, + builder: (_, vm) { + return Text('${totalCalc(vm.calcItems)} тнг', + style: TextStyle( + fontWeight: FontWeight.bold, + color: whiteColor, + fontSize: 35)); + }); + } + return StoreConnector( + converter: (store) => store.state.kassaState, + builder: (_, vm) { + return Text('${totalKassa(vm.kassaItems)} тнг', + style: TextStyle( + fontWeight: FontWeight.bold, + color: whiteColor, + fontSize: 35)); + }); + } + + String totalKassa(List kassaItems) { + num total = 0.0; + kassaItems.forEach((element) { + total += element.total == null ? 0.0 : element.total.toDouble(); + }); + return total.toString(); + } + + String totalCalc(List items) { + num total = 0.0; + items.forEach((element) { + if (element.operation == Calculations.MULTIPLY) { + double num1 = element.num1 == null ? 0.0 : double.parse(element.num1); + double num2 = element.num2 == null ? 0.0 : double.parse(element.num2); + total += num1 * num2; + } else { + total += element.num1 == null ? 0.0 : double.parse(element.num1); + } + }); + return total.toString(); + } +} diff --git a/lib/views/payment_nfc/widgets/background_view.dart b/lib/views/payment_nfc/widgets/background_view.dart new file mode 100644 index 0000000..9856ef1 --- /dev/null +++ b/lib/views/payment_nfc/widgets/background_view.dart @@ -0,0 +1,17 @@ +import 'package:aman_kassa_flutter/shared/app_colors.dart'; +import 'package:flutter/cupertino.dart'; +import 'package:flutter_screenutil/screenutil.dart'; + +class BackgroundView extends StatelessWidget { + @override + Widget build(BuildContext context) { + return Center( + heightFactor: 1.5, + child: Container( + height: ScreenUtil().setSp(250.0), + width: ScreenUtil().setSp(250.0), + decoration: + BoxDecoration(color: purpleSecondColor, shape: BoxShape.circle), + )); + } +} diff --git a/lib/views/payment_nfc/widgets/card_view.dart b/lib/views/payment_nfc/widgets/card_view.dart new file mode 100644 index 0000000..bc5c717 --- /dev/null +++ b/lib/views/payment_nfc/widgets/card_view.dart @@ -0,0 +1,42 @@ +import 'package:aman_kassa_flutter/shared/ui_helpers.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_screenutil/screenutil.dart'; + +class CardView extends StatefulWidget { + + final bool show; + + const CardView({this.show = false }); + + @override + _CardViewState createState() => _CardViewState(); +} + +class _CardViewState extends State { + @override + Widget build(BuildContext context) { + return Positioned( + child: AnimatedOpacity( + opacity: widget.show? 1 : 0.0, + duration: Duration(seconds: 1), + child: AnimatedContainer( + height: ScreenUtil().setSp(250), + width: ScreenUtil().setSp(250), + transform: Matrix4.translationValues(widget.show? ScreenUtil().setSp(20.0) : 0.0, widget.show? ScreenUtil().setSp(-20.0) : 0.0, 0) + //..rotateZ(widget.show? -0.2:0.0) + , + duration: const Duration(milliseconds: 1500), + curve: Curves.fastOutSlowIn, + child: Container( + //color: Colors.red.withOpacity(0.1), + //alignment: Alignment.bottomCenter, + child: Image.asset( + 'assets/images/card.png', + fit: BoxFit.contain, + ), + ), + ), + ), + ); + } +} diff --git a/lib/views/payment_nfc/widgets/phone_view.dart b/lib/views/payment_nfc/widgets/phone_view.dart new file mode 100644 index 0000000..24d44c5 --- /dev/null +++ b/lib/views/payment_nfc/widgets/phone_view.dart @@ -0,0 +1,111 @@ +import 'package:aman_kassa_flutter/shared/app_colors.dart'; +import 'package:aman_kassa_flutter/shared/ui_helpers.dart'; +import 'package:auto_size_text/auto_size_text.dart'; +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_screenutil/screenutil.dart'; +import 'package:material_design_icons_flutter/material_design_icons_flutter.dart'; + +class PhoneView extends StatefulWidget { + final bool scaled; + final int status; + + const PhoneView({this.scaled = false, this.status }); + + @override + _PhoneViewState createState() => _PhoneViewState(); +} + +class _PhoneViewState extends State { + @override + Widget build(BuildContext context) { + return AnimatedContainer( + alignment: Alignment.topCenter, + transform: Matrix4.translationValues(widget.scaled? ScreenUtil().setHeight(120) : 0.0, widget.scaled? ScreenUtil().setHeight(50) : 0.0, 0) + ..scale(widget.scaled? ScreenUtil().setSp(0.65) : 1.0)..rotateZ(widget.scaled? ScreenUtil().setSp(-0.2):0.0), + duration: const Duration(milliseconds: 1500), + curve: Curves.fastOutSlowIn, + child: Container( + width: ScreenUtil().setSp(380.0), + height: ScreenUtil().setSp(520.0), + //color: Colors.red.withOpacity(0.1), + child: Stack( + alignment: Alignment.center, + children: [ + Container( + width: ScreenUtil().setSp(210.0), + height: ScreenUtil().setSp(430.0), + decoration: BoxDecoration( + color: Colors.white + ), + child: Center( + child: AnimatedSwitcher(child: buildContent(), duration: const Duration( milliseconds: 300),), + ), + ), + Image.asset( + 'assets/images/phone_fit.png', + fit: BoxFit.fitWidth, + width: ScreenUtil().setSp(260.0), + height: ScreenUtil().setSp(500.0), + ), + ], + ), + ), + ); + } + + Widget buildContent() { + if(widget.status == 0){ + return Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Icon(MdiIcons.timerSand, color: yellowColor,size: ScreenUtil().setSp(90.0),), + verticalSpaceSmall, + AutoSizeText('Инициализация', style: TextStyle(fontWeight: FontWeight.bold),) + ], + ); + } + if(widget.status == 1){ + return Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Icon(MdiIcons.nfc, color: primaryColor,size: ScreenUtil().setSp(90.0),), + verticalSpaceSmall, + AutoSizeText('Ожидание карты', style: TextStyle(fontWeight: FontWeight.bold),) + ], + ); + } + if(widget.status == 2){ + return Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Icon(MdiIcons.shieldSearch, color: yellowColor,size: ScreenUtil().setSp(90.0),), + verticalSpaceSmall, + AutoSizeText('Проверка', style: TextStyle(fontWeight: FontWeight.bold),) + ], + ); + } + if(widget.status == 3){ + return Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Icon(MdiIcons.checkBold, color: greenColor,size: ScreenUtil().setSp(90.0),), + verticalSpaceSmall, + AutoSizeText('Оплачено', style: TextStyle(fontWeight: FontWeight.bold),) + ], + ); + } + if(widget.status == 4){ + return Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Icon(MdiIcons.closeOctagon, color: redColor,size: ScreenUtil().setSp(90.0),), + verticalSpaceSmall, + AutoSizeText('Ошибка', style: TextStyle(fontWeight: FontWeight.bold),) + ], + ); + } + + return Container(); + } +} diff --git a/lib/views/payment_nfc/widgets/text_state.dart b/lib/views/payment_nfc/widgets/text_state.dart new file mode 100644 index 0000000..e59cd2f --- /dev/null +++ b/lib/views/payment_nfc/widgets/text_state.dart @@ -0,0 +1,84 @@ +import 'package:aman_kassa_flutter/shared/app_colors.dart'; +import 'package:auto_size_text/auto_size_text.dart'; +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_screenutil/flutter_screenutil.dart'; + +class TextStateView extends StatelessWidget { + final int status; + final String text; + + const TextStateView({Key key, this.status, this.text = ''}) : super(key: key); + + @override + Widget build(BuildContext context) { + return Positioned( + bottom: ScreenUtil().setSp(25), + left: ScreenUtil().setSp(25), + right: ScreenUtil().setSp(25), + child: AnimatedSwitcher( + duration: const Duration(milliseconds: 300), + child: buildAutoSizeText())); + } + + AutoSizeText buildAutoSizeText() { + switch(status) { + case 0: + return AutoSizeText( + 'Инициализация', + key: UniqueKey(), + style: TextStyle( + fontSize: ScreenUtil().setSp(25.0), + color: whiteColor), + ); + break; + case 1: + return AutoSizeText( + 'Сканирование', + key: UniqueKey(), + style: TextStyle( + fontSize: ScreenUtil().setSp(25.0), + color: whiteColor), + ); + break; + case 2: + return AutoSizeText( + 'Проверка данных', + key: UniqueKey(), + style: TextStyle( + fontSize: ScreenUtil().setSp(25.0), + color: whiteColor), + ); + break; + case 3: + return AutoSizeText( + 'Платеж прошел успешно', + key: UniqueKey(), + style: TextStyle( + fontSize: ScreenUtil().setSp(25.0), + color: whiteColor), + ); + break; + case 4: + return AutoSizeText( + 'Ошибка', + key: UniqueKey(), + style: TextStyle( + fontSize: ScreenUtil().setSp(25.0), + color: whiteColor), + ); + break; + default: + return AutoSizeText( + text, + key: UniqueKey(), + style: TextStyle( + fontSize: ScreenUtil().setSp(25.0), + color: whiteColor), + ); + } + + + + } +} diff --git a/lib/views/start_up/start_up_view.dart b/lib/views/start_up/start_up_view.dart index eaa0b08..5f9bc47 100644 --- a/lib/views/start_up/start_up_view.dart +++ b/lib/views/start_up/start_up_view.dart @@ -3,6 +3,7 @@ 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:flutter_screenutil/screenutil.dart'; class StartUpView extends StatefulWidget { @@ -20,6 +21,9 @@ class _StartUpViewState extends State { @override Widget build(BuildContext context) { + print(MediaQuery.of(context).size.width); + print(MediaQuery.of(context).size.height); + ScreenUtil.init(context, width: 411.43, height: 683.43, allowFontScaling: false); return StoreConnector( converter: (store) => store.state.userState, builder: (context, userState) { diff --git a/pubspec.lock b/pubspec.lock index 5d9b1f1..452ac19 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -91,7 +91,7 @@ packages: name: equatable url: "https://pub.dartlang.org" source: hosted - version: "1.2.2" + version: "1.2.3" esys_flutter_share: dependency: "direct main" description: @@ -125,6 +125,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "0.6.0" + flutter_screenutil: + dependency: "direct main" + description: + name: flutter_screenutil + url: "https://pub.dartlang.org" + source: hosted + version: "2.3.1" flutter_test: dependency: "direct dev" description: flutter @@ -141,7 +148,7 @@ packages: name: get_it url: "https://pub.dartlang.org" source: hosted - version: "4.0.2" + version: "4.0.4" google_fonts: dependency: "direct main" description: @@ -183,7 +190,7 @@ packages: name: logger url: "https://pub.dartlang.org" source: hosted - version: "0.9.1" + version: "0.9.2" mask_text_input_formatter: dependency: "direct main" description: @@ -344,7 +351,7 @@ packages: name: redux url: "https://pub.dartlang.org" source: hosted - version: "4.0.0" + version: "4.0.0+3" redux_persist: dependency: "direct main" description: diff --git a/pubspec.yaml b/pubspec.yaml index 7418630..35d3b46 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -7,16 +7,16 @@ dependencies: flutter: sdk: flutter cupertino_icons: ^0.1.3 - redux: ^4.0.0 + redux: ^4.0.0+3 flutter_redux: ^0.6.0 redux_thunk: ^0.3.0 redux_persist: ^0.8.4 redux_persist_flutter: ^0.8.2 responsive_builder: ^0.2.0+2 provider: ^4.3.1 - logger: ^0.9.1 - get_it: ^4.0.2 - equatable: ^1.2.2 + logger: ^0.9.2 + get_it: ^4.0.4 + equatable: ^1.2.3 http: ^0.12.2 sqflite: ^1.3.1 path_provider: ^1.6.11 @@ -30,6 +30,7 @@ dependencies: url_launcher: ^5.5.0 qr_flutter: ^3.2.0 mask_text_input_formatter: ^1.0.7 + flutter_screenutil: ^2.3.1 dev_dependencies: flutter_test: sdk: flutter @@ -39,8 +40,7 @@ flutter: # To add assets to your application, add an assets section, like this: assets: - - assets/images/logo.png - - assets/images/icon_large.png + - assets/images/ - assets/lang/en.json - assets/lang/ru.json