diff --git a/lib/core/services/data_service.dart b/lib/core/services/data_service.dart index 5e7bf50..cc46259 100644 --- a/lib/core/services/data_service.dart +++ b/lib/core/services/data_service.dart @@ -95,4 +95,21 @@ class DataService extends BaseService { ..articul = product.article?.toString(); return item; } + + Future getTransactionDataById(int? id) async { + if(id == null) return null; + try { + Map? map = await _db.queryById(transactionTableName, id); + if (map != null) { + final Transaction transaction = Transaction.fromMap(map); + final String? data = transaction.data; + if (data != null) { + return TransactionData.fromMap(jsonDecode(data)); + } + } + } catch (e, stack) { + log.e('getTransactionDataById', e, stack); + } + return null; + } } diff --git a/lib/routes/route_names.dart b/lib/routes/route_names.dart index 90a54ec..c9b4ecb 100644 --- a/lib/routes/route_names.dart +++ b/lib/routes/route_names.dart @@ -7,10 +7,9 @@ const String addByBarcodeViewRoute = 'AddByBarcodeView'; const String contragentSelectViewRoute = 'ContragentSelectViewRoute'; const String paymentViewRoute = 'paymentViewRoute'; +const String receiptViewRoute = 'receiptViewRoute'; const String settingPrinterBluetoothViewRoute = 'SettingPrinterBluetoothView'; -const String settingPrinterBleBluetoothView = 'SettingPrinterBleBluetoothView'; -const String settingPrinterBlueView = 'settingPrinterBlueView'; // Generate the views here diff --git a/lib/routes/router.dart b/lib/routes/router.dart index 04066b2..2396f62 100644 --- a/lib/routes/router.dart +++ b/lib/routes/router.dart @@ -1,23 +1,22 @@ +import 'package:flutter/material.dart'; import 'package:satu/core/models/dictionary/category_row_data.dart'; import 'package:satu/core/models/dictionary/good_row_data.dart'; +import 'package:satu/core/models/entity_data/transaction_data.dart'; import 'package:satu/views/dictionaries/category/category_edit.dart'; import 'package:satu/views/dictionaries/category/category_select_view.dart'; -import 'package:satu/views/dictionaries/category/category_view.dart'; import 'package:satu/views/dictionaries/goods/goods_edit.dart'; -import 'package:satu/views/dictionaries/goods/goods_view.dart'; +import 'package:satu/views/login/login_view.dart'; +import 'package:satu/views/main/main_view.dart'; import 'package:satu/views/settings/printer_bluetooth/printer_view.dart'; import 'package:satu/views/work/views/add_by_barcode/add_by_barcode_view.dart'; import 'package:satu/views/work/views/add_product/add_product_view.dart'; -import 'package:satu/views/login/login_view.dart'; -import 'package:satu/views/main/main_view.dart'; -import 'package:satu/views/settings/printer_bluetooth/printer_select.dart'; import 'package:satu/views/work/views/contragent/select_contragent_view.dart'; import 'package:satu/views/work/views/payment/payment_view.dart'; +import 'package:satu/views/work/views/receipt/receipt_view.dart'; import 'package:satu/views/work/work_view.dart'; import './route_names.dart'; -import 'package:flutter/material.dart'; Route generateRoute(RouteSettings settings) { switch (settings.name) { @@ -80,13 +79,13 @@ Route generateRoute(RouteSettings settings) { viewToShow: GoodEdit(good: good,), ); - // case ImageShowRoute: - // ImageShowModel data = settings.arguments as ImageShowModel; - // //return SlideRightRoute(widget: ImageShowContainer(data)); - // return _getPageRoute( - // routeName: settings.name, - // viewToShow: ImageShowContainer(data), - // ); + case receiptViewRoute: + final TransactionData data = settings.arguments! as TransactionData; + //return SlideRightRoute(widget: ImageShowContainer(data)); + return _getPageRoute( + routeName: settings.name, + viewToShow: ReceiptView(transactionData: data,), + ); default: return MaterialPageRoute( builder: (_) => Scaffold( diff --git a/lib/views/work/tabs/component/contagent_select_bar.dart b/lib/views/work/tabs/component/contagent_select_bar.dart index 6807cb6..a0d5369 100644 --- a/lib/views/work/tabs/component/contagent_select_bar.dart +++ b/lib/views/work/tabs/component/contagent_select_bar.dart @@ -23,7 +23,7 @@ class ContragentSelectBar extends StatelessWidget { locator().push(contragentSelectViewRoute); }, child: Padding( - padding: EdgeInsets.symmetric(vertical: 8.w, horizontal: 15.w), + padding: EdgeInsets.symmetric(vertical:08.w, horizontal: 15.w), child: Row( children: [ Expanded( diff --git a/lib/views/work/tabs/journal_view.dart b/lib/views/work/tabs/journal_view.dart index 54b6b4f..bf319c2 100644 --- a/lib/views/work/tabs/journal_view.dart +++ b/lib/views/work/tabs/journal_view.dart @@ -1,10 +1,15 @@ import 'package:flutter/material.dart'; import 'package:flutter_redux/flutter_redux.dart'; import 'package:grouped_list/grouped_list.dart'; +import 'package:satu/core/models/entity_data/transaction_data.dart'; import 'package:satu/core/models/flow/dao/transaction_dao.dart'; import 'package:satu/core/redux/actions/journal_actions.dart'; import 'package:satu/core/redux/state/journal_state.dart'; import 'package:satu/core/redux/store.dart'; +import 'package:satu/core/services/data_service.dart'; +import 'package:satu/core/services/navigator_service.dart'; +import 'package:satu/core/utils/locator.dart'; +import 'package:satu/routes/route_names.dart'; import 'package:satu/shared/app_colors.dart'; import 'package:satu/widgets/bar/products_app_bar.dart'; import 'package:satu/widgets/buttons/option_pill.dart'; @@ -17,6 +22,9 @@ class JournalView extends StatefulWidget { } class _JournalViewState extends State { + final DataService _dataService = locator(); + final NavigatorService _navigatorService = locator(); + int tabIndex = 0; @override @@ -30,6 +38,7 @@ class _JournalViewState extends State { return Scaffold( appBar: const ProductsAppBar( title: 'Журнал транзакции', + drawerShow: true, ), body: StoreConnector( converter: (store) => store.state.journalState!, @@ -38,9 +47,7 @@ class _JournalViewState extends State { crossAxisAlignment: CrossAxisAlignment.start, children: [ Container( - decoration: const BoxDecoration( - color: whiteColor - ), + decoration: const BoxDecoration(color: whiteColor), child: Padding( padding: const EdgeInsets.all(15.0), child: Row( @@ -105,6 +112,9 @@ class _JournalViewState extends State { date: element.date!, amount: element.total, received: element.received, + onPress: () { + pushToReceiptView(element); + }, ), itemComparator: (item1, item2) => item1.day!.compareTo(item2.day!), @@ -122,4 +132,13 @@ class _JournalViewState extends State { }), ); } + + Future pushToReceiptView(TransactionDao element) async { + final int? id = element.id; + TransactionData? transactionData = + await _dataService.getTransactionDataById(id); + if(transactionData != null) { + _navigatorService.push(receiptViewRoute, arguments: transactionData); + } + } } diff --git a/lib/views/work/tabs/sell_view.dart b/lib/views/work/tabs/sell_view.dart index 9d1cc31..9d0e6d8 100644 --- a/lib/views/work/tabs/sell_view.dart +++ b/lib/views/work/tabs/sell_view.dart @@ -35,7 +35,7 @@ class SellView extends StatelessWidget { backgroundColor: backgroundColor, childHeight: 60, child: ProductHeaderBar( - count: state.items!.length, + count: state.items!.length, sum: sumProducts(state.items!), ), ), diff --git a/lib/views/work/views/receipt/receipt_view.dart b/lib/views/work/views/receipt/receipt_view.dart index e69de29..1adbeb3 100644 --- a/lib/views/work/views/receipt/receipt_view.dart +++ b/lib/views/work/views/receipt/receipt_view.dart @@ -0,0 +1,51 @@ +import 'dart:convert'; + +import 'package:flutter/material.dart'; +import 'package:satu/core/models/entity_data/transaction_data.dart'; +import 'package:satu/core/models/flow/sell_response.dart'; +import 'package:satu/shared/app_colors.dart'; +import 'package:satu/widgets/bar/products_app_bar.dart'; + +class ReceiptView extends StatelessWidget { + const ReceiptView({ + required this.transactionData, + Key? key, + }) : super(key: key); + + final TransactionData transactionData; + + @override + Widget build(BuildContext context) { + return Scaffold( + backgroundColor: whiteColor, + appBar: const ProductsAppBar( + title: 'Просмотр чека', + ), + body: Column( + children: [ + Expanded( + child: SingleChildScrollView( + physics: const BouncingScrollPhysics(), + child: Center(child: imageFromBase64String(transactionData.sellResponse)), + ), + ) + ], + )); + } +} + +Widget imageFromBase64String(SellResponse? sellResponse) { + final String? base64String = sellResponse?.checkPng; + if (base64String == null) { + return const Padding( + padding: EdgeInsets.symmetric(vertical: 10.0, horizontal: 8.0), + child: Center( + child: Text('Отсутсвует информация о чеке'), + ), + ); + } + return Padding( + padding: const EdgeInsets.symmetric(vertical: 10.0, horizontal: 8.0), + child: Image.memory(base64Decode(base64String)), + ); +} diff --git a/lib/widgets/bar/products_app_bar.dart b/lib/widgets/bar/products_app_bar.dart index 0c55bef..7d393bb 100644 --- a/lib/widgets/bar/products_app_bar.dart +++ b/lib/widgets/bar/products_app_bar.dart @@ -8,7 +8,7 @@ class ProductsAppBar extends StatelessWidget implements PreferredSizeWidget { final String? title; final List? actions; final Widget? child; - final int? childHeight; + final double childHeight; final double elevation; final Color? backgroundColor; final bool drawerShow; @@ -32,8 +32,8 @@ class ProductsAppBar extends StatelessWidget implements PreferredSizeWidget { child: Container( decoration: BoxDecoration( image: DecorationImage( - image: AssetImage('assets/images/top_bar_bg.png'), - fit: BoxFit.fitWidth, + image: const AssetImage('assets/images/top_bar_bg.png'), + fit: childHeight > 0 ? BoxFit.cover : BoxFit.fitWidth, alignment: FractionalOffset.topLeft, ), ), @@ -42,25 +42,32 @@ class ProductsAppBar extends StatelessWidget implements PreferredSizeWidget { mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ AppBar( - title: Text(title ?? ''), + title: Text( + title ?? '', + style: const TextStyle(color: blackColor, fontSize: 14), + ), + iconTheme: const IconThemeData( + color: blackColor, //change your color here + ), centerTitle: true, backgroundColor: Colors.transparent, elevation: 0.0, - leading: drawerShow ? IconButton( - icon: Icon( - Icons.menu, - color: blackColor, - ), - onPressed: () { - locator() - .scaffoldDrawerKey - .currentState! - .openDrawer(); - }, - ) : null , + leading: drawerShow + ? IconButton( + icon: const Icon( + Icons.menu, + ), + onPressed: () { + locator() + .scaffoldDrawerKey + .currentState! + .openDrawer(); + }, + ) + : null, actions: actions, ), - if (child != null && childHeight! > 0) child!, + if (child != null && childHeight > 0) child!, ], ), ), @@ -69,6 +76,6 @@ class ProductsAppBar extends StatelessWidget implements PreferredSizeWidget { @override Size get preferredSize { - return new Size.fromHeight(60.0 + childHeight!); + return Size.fromHeight(60.0 + childHeight); } } diff --git a/lib/widgets/bar/products_header_bar.dart b/lib/widgets/bar/products_header_bar.dart index f05bbf9..ba2f446 100644 --- a/lib/widgets/bar/products_header_bar.dart +++ b/lib/widgets/bar/products_header_bar.dart @@ -5,32 +5,33 @@ import 'package:satu/shared/shared_styles.dart'; import 'package:satu/widgets/dialog/modal_select_dialog.dart'; class ProductHeaderBar extends StatelessWidget { + const ProductHeaderBar({required this.count, required this.sum , Key? key}) + : super(key: key); + final int count; final num sum; - const ProductHeaderBar({Key? key, required this.count, required this.sum}) - : super(key: key); @override Widget build(BuildContext context) { return Padding( - padding: EdgeInsets.symmetric(horizontal: 15.w, vertical: 10.w), + padding: const EdgeInsets.symmetric(horizontal: 15, vertical: 10), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( 'Итого: $sum тнг', - style: TextStyle( + style: const TextStyle( fontWeight: FontWeight.w700, color: blackColor, - fontSize: ScreenUtil().setSp(20)), + fontSize: 20), ), Text( 'Товаров выбрано: $count', - style: TextStyle( + style: const TextStyle( fontWeight: FontWeight.w400, color: blackColor, - fontSize: ScreenUtil().setSp(15)), + fontSize: 12), ), ], ), diff --git a/lib/widgets/bar/products_title_bar.dart b/lib/widgets/bar/products_title_bar.dart index f405f4b..84d8be3 100644 --- a/lib/widgets/bar/products_title_bar.dart +++ b/lib/widgets/bar/products_title_bar.dart @@ -1,18 +1,22 @@ import 'package:flutter/material.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; +import 'package:satu/core/models/dialog_models.dart'; import 'package:satu/core/redux/actions/sell_actions.dart'; import 'package:satu/core/redux/store.dart'; +import 'package:satu/core/services/dialog_service.dart'; +import 'package:satu/core/utils/locator.dart'; import 'package:satu/shared/app_colors.dart'; class ProductsTitleBarBar extends StatelessWidget { - const ProductsTitleBarBar( - {required this.title , Key? key, this.itemsExist = false}) - : super(key: key); + const ProductsTitleBarBar({ + required this.title, + Key? key, + this.itemsExist = false, + }) : super(key: key); final bool itemsExist; final String title; - @override Widget build(BuildContext context) { return Padding( @@ -20,43 +24,33 @@ class ProductsTitleBarBar extends StatelessWidget { child: Row( children: [ Expanded( - child: Padding( - padding: const EdgeInsets.symmetric(vertical: 10), - child: Text( - title, - style: const TextStyle(fontSize: 12, color: placeholderColor), + child: Padding( + padding: const EdgeInsets.symmetric(vertical: 10), + child: Text( + title, + style: const TextStyle(fontSize: 12, color: placeholderColor), + ), ), - )), + ), if (itemsExist) TextButton( - onPressed: () async { - final bool? result = await showDialog( - context: context, - builder: (BuildContext context) { - return AlertDialog( - title: const Text('Внимание'), - content: const Text('Удалить все товары из списка'), - actions: [ - TextButton( - onPressed: () => - Navigator.of(context).pop(true), - child: const Text('Удалить')), - TextButton( - onPressed: () => Navigator.of(context).pop(false), - child: const Text('Отмена'), - ), - ], - ); - }, - ); - if (result == true) { - Redux.store!.dispatch(removeAllSellData); - } - }, - child: Text( - 'Удалить все', - style: TextStyle(fontSize: 16.sp, color: dangerColor), - )) + onPressed: () async { + final DialogResponse response = + await locator().showConfirmationDialog( + title: 'Внимание', + description: 'Удалить все товары из списка?', + confirmationTitle: 'Удалить', + cancelTitle: 'Отмена', + ); + if (response.confirmed == true) { + Redux.store!.dispatch(removeAllSellData); + } + }, + child: Text( + 'Удалить все', + style: TextStyle(fontSize: 16.sp, color: dangerColor), + ), + ) ], ), );