aman-kassa-flutter/lib/views/check/image_show_container.dart

436 lines
16 KiB
Dart
Raw Permalink Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

import 'dart:convert';
import 'dart:io';
import 'package:aman_kassa_flutter/core/entity/Voucher.dart';
import 'dart:typed_data';
import 'package:aman_kassa_flutter/core/locator.dart';
import 'package:aman_kassa_flutter/core/models/check_data.dart';
import 'package:aman_kassa_flutter/core/models/check_image_modal.dart';
import 'package:aman_kassa_flutter/core/models/aman_dao.dart';
import 'package:aman_kassa_flutter/core/models/card_data.dart';
import 'package:aman_kassa_flutter/core/models/dialog_models.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/BankService.dart';
import 'package:aman_kassa_flutter/core/services/DataService.dart';
import 'package:aman_kassa_flutter/core/services/blue_print_service.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/setting_actions.dart';
import 'package:aman_kassa_flutter/redux/actions/user_actions.dart';
import 'package:aman_kassa_flutter/redux/constants/setting_const.dart';
import 'package:aman_kassa_flutter/redux/state/setting_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/settings/printer/PrinterTest.dart';
import 'package:aman_kassa_flutter/views/payment/halyk_pos_service.dart';
import 'package:aman_kassa_flutter/widgets/fields/busy_button_icon.dart';
import 'package:aman_kassa_flutter/widgets/loader/Dialogs.dart';
import 'package:bluetooth_print/bluetooth_print_model.dart';
import 'package:esc_pos_utils/esc_pos_utils.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:material_design_icons_flutter/material_design_icons_flutter.dart';
import 'package:vocsy_esys_flutter_share/vocsy_esys_flutter_share.dart';
import 'package:url_launcher/url_launcher.dart';
import '../../core/models/aman_dao.dart';
class ImageShowContainer extends StatefulWidget {
final ImageShowModel showModel;
ImageShowContainer(this.showModel);
@override
_ImageShowContainerState createState() => _ImageShowContainerState();
}
class _ImageShowContainerState extends State<ImageShowContainer> {
final BluePrintService printerManager = locator<BluePrintService>();
final DialogService _dialogService = locator<DialogService>();
final BluetoothDevice? printerBtDevice =
Redux.store!.state.settingState!.printerBT;
bool _printing = false;
void _preparePrint() async {
if (Platform.isIOS) {
_print();
} else {
printerManager.state.listen((val) {
print("state = $val");
if (!mounted) return;
if (val == 12) {
print('on');
_print();
} else if (val == 10) {
print('off');
_dialogService.showDialog(
description: 'Отсутвует соеденение Bluetooth или он отключен',
title: 'Bluetooth');
}
print('state is $val');
});
}
}
@override
void dispose() {
disconnect();
super.dispose();
}
void disconnect() async {
await printerManager.disconnect();
}
void _print() async {
final SettingState state = Redux.store!.state.settingState!;
if (state.printerBT == null) {
_dialogService.showDialog(
description: 'Укажите в настройках принтер для печати чеков');
return;
}
bool isIos = Platform.isIOS;
int chunkSizeBytes = 3096;
int queueSleepTimeMs = 100;
if (isIos) {
chunkSizeBytes = 75;
queueSleepTimeMs = 10;
}
setState(() {
_printing = true;
});
try {
printerManager.device = state.printerBT!;
await printerManager.connect();
PaperSize paper = state.printerPaperSize == SettingPrinterPaperM80
? PaperSize.mm80
: PaperSize.mm58;
if (SettingPrinterEncodingImage == state.printerEncoding) {
final bool res = await printerManager.printBytes(
Uint8List.fromList(await printImageCheck(paper, widget.showModel.data!.base64Data!)));
if (!res) {
_dialogService.showDialog(description: 'Ошибка при печати');
}
} else {
final bool res = await printerManager.printBytes(
Uint8List.fromList(await printTextCheck(paper, state.printerEncoding!,
jsonDecode(widget.showModel.data!.textData!)))
);
if (!res) {
_dialogService.showDialog(description: 'Ошибка при печати');
}
}
} catch (e) {
print(e);
}
await Future.delayed(Duration(seconds: 15));
setState(() {
_printing = false;
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
//backgroundColor: fillColor,
title: Text(widget.showModel.title),
actions: [
if (_printing)
Padding(
padding: const EdgeInsets.only(right: 8.0),
child: SizedBox(
width: 36.0,
child: Center(
child: CircularProgressIndicator(
strokeWidth: 2,
valueColor: new AlwaysStoppedAnimation<Color>(whiteColor),
),
),
),
)
else
IconButton(icon: Icon(Icons.print), onPressed: _preparePrint)
],
),
body: ListView(
children: <Widget>[
imageFromBase64String(widget.showModel.data!.base64Data!)
],
),
floatingActionButton: MyFloatingActionButton(widget.showModel),
);
}
}
Padding imageFromBase64String(String base64String) {
return Padding(
padding: const EdgeInsets.symmetric(vertical: 10.0, horizontal: 8.0),
child: Image.memory(base64Decode(base64String)),
);
}
class ImageShowModel {
final CheckImageModal? data;
final String title;
final String? url;
final CardData? cardData;
final Voucher? voucher;
ImageShowModel({this.data, required this.title, this.url, this.cardData, this.voucher});
}
class MyFloatingActionButton extends StatefulWidget {
final ImageShowModel data;
MyFloatingActionButton(this.data);
@override
_MyFloatingActionButtonState createState() => _MyFloatingActionButtonState();
}
class _MyFloatingActionButtonState extends State<MyFloatingActionButton> {
bool showFab = true;
DialogService _dialog = locator<DialogService>();
NavigatorService _navigatorService = locator<NavigatorService>();
final GlobalKey<State> _keyLoader = new GlobalKey<State>();
final DataService _dataService = locator<DataService>();
double sheetHeight = 260;
@override
Widget build(BuildContext context) {
//print(widget.data.cardData.transactionType);
if (showFab) {
return Column(
mainAxisAlignment: MainAxisAlignment.end,
children: [
if (widget.data.cardData?.transactionType == "payment")
FloatingActionButton(
backgroundColor: redColor,
tooltip: 'Отмена',
child: Icon(
Icons.cancel,
color: whiteColor,
),
onPressed: () async {
var today = new DateTime.now();
var yesterday = today.subtract(new Duration(days: 1));
if(Redux.store?.state.userState?.smena?.startedAt == null
|| yesterday.isAfter(Redux.store!.state.userState!.smena!.startedAt!)) {
_dialog.showDialog(description: 'Текущая смена открыта более 24 ч. Необходимо закрыть смену и открыть ее заново.');
return;
}
try {
await Redux.store!.dispatch(changePinSkipFromSetting(true));
AmanDao<CardData> response = await reversalHalykPos(widget.data.cardData!, widget.data.voucher!.total!);
if (response.success == true) {
pressRefund();
} else {
_dialog.showDialog(description: response.msg!);
}
} finally {
await Redux.store!.dispatch(changePinSkipFromSetting(false));
}
_navigatorService.replace(HomeViewRoute);
},
heroTag: null,
)
else
SizedBox(
height: 0,
),
SizedBox(
height: 10,
),
if (widget.data.cardData != null && widget.data.cardData?.transactionType == "payment")
FloatingActionButton(
backgroundColor: redColor,
tooltip: 'Возврат',
child: Icon(
Icons.settings_backup_restore,
color: whiteColor,
),
onPressed: () async {
var today = new DateTime.now();
var yesterday = today.subtract(new Duration(days: 1));
if( Redux.store!.state.userState == null
|| Redux.store!.state.userState?.smena == null
|| Redux.store!.state.userState?.smena?.startedAt == null
|| yesterday.isAfter(Redux.store!.state.userState!.smena!.startedAt!)) {
_dialog.showDialog(description: 'Текущая смена открыта более 24 ч. Необходимо закрыть смену и открыть ее заново.');
return;
}
try {
await Redux.store!.dispatch(changePinSkipFromSetting(true));
AmanDao<CardData> response = await refundHalykPos(widget.data.cardData!, widget.data.voucher!.total!);
if (response.success == true) {
pressRefund();
} else {
_dialog.showDialog(description: response.msg!);
}
} finally {
await Redux.store!.dispatch(changePinSkipFromSetting(false));
}
},
heroTag: null,
)
else
SizedBox(
height: 0,
),
SizedBox(
height: 10,
),
FloatingActionButton(
child: Icon(Icons.share),
onPressed: () {
var bottomSheetController = showBottomSheet(
context: context,
builder: (bottomSheetContext) => Container(
padding: const EdgeInsets.symmetric(horizontal: 10.0),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.all(Radius.circular(15)),
boxShadow: [BoxShadow(blurRadius: 10, color: Colors.grey[300]!, spreadRadius: 5)]),
height: 260,
child: Column(
children: <Widget>[
verticalSpaceSmall,
BusyButtonIcon(
title: 'WhatsApp',
onPressed: callWhatsApp,
mainColor: greenColor,
icon: MdiIcons.whatsapp,
enabled: widget.data.url != null,
),
verticalSpaceSmall,
BusyButtonIcon(
title: 'QR-код чека',
onPressed: qrGenerate,
mainColor: primaryColor,
icon: MdiIcons.qrcode,
enabled: widget.data.url != null,
),
verticalSpaceSmall,
BusyButtonIcon(
title: 'Поделиться',
onPressed: shareFile,
mainColor: yellowColor,
icon: Icons.share,
),
],
)));
showFloatingActionButton(false);
bottomSheetController.closed.then((value) {
showFloatingActionButton(true);
});
},
),
],
);
} else {
return Container();
}
}
pressRefund() async {
Dialogs.showLoadingDialog(context, _keyLoader);
try {
AppState _state = Redux.store!.state;
String _token = _state.userState!.user!.token!;
CardData _cardData = widget.data.cardData!;
CheckData _checkData = CheckData.fromJson(json.decode(widget.data.voucher!.data!));
Response<dynamic>? response =
await _dataService.refundM4Bank(token: _token, cardData: _cardData, checkData: _checkData);
if (response != null) {
if (response.operation) {
String message = response.body['message'];
String check = response.body['check'];
var checkText = response.body['check_text'];
String url = response.body['link'];
print('url : $url');
Redux.store!.dispatch(checkMoney);
Redux.store!.dispatch(openSmenaPseudo);
Navigator.of(_keyLoader.currentContext!, rootNavigator: true).pop();
_navigatorService.replace(HomeViewRoute);
_navigatorService.push(ImageShowRoute,
arguments: ImageShowModel(
data: new CheckImageModal(
base64Data: check, textData: checkText != null ? jsonEncode(checkText) : null),
title: message,
url: url));
} else if (!response.operation && ![401, 402, 403, 412, 500].contains(response.status)) {
Navigator.of(_keyLoader.currentContext!, rootNavigator: true).pop();
_dialog.showDialog(description: response.body['message']);
} else {
Navigator.of(_keyLoader.currentContext!, rootNavigator: true).pop();
}
} else {
Navigator.of(_keyLoader.currentContext!, rootNavigator: true).pop();
}
} catch (e) {
print(e);
Navigator.of(_keyLoader.currentContext!, rootNavigator: true).pop();
}
}
void shareFile() async {
try {
await Share.file('Aman Kassa', 'aman_kassa_check.png', base64Decode(widget.data.data!.base64Data!), 'image/png');
} catch (e) {
print('error: $e');
}
}
void qrGenerate() async {
_navigatorService.push(QrViewRoute, arguments: ImageShowModel(url: widget.data.url, title: 'Спасибо за покупку'));
}
void callWhatsApp() async {
DialogResponse response = await _dialog.showConfirmationDialogInput(
description: 'Номер телефона', cancelTitle: 'Отмена', confirmationTitle: 'Отправить', formatType: 'phone');
if (response.confirmed) {
String phoneNumber = response.responseText!;
String msg = "Спасибо за покупку! \r\n ${widget.data.url} ";
launchWhatsApp(phone: phoneNumber, message: msg);
}
}
void launchWhatsApp({
required String phone,
required String message,
}) async {
String url() {
if (Platform.isIOS) {
return "whatsapp://wa.me/$phone/?text=${Uri.encodeFull(message)}";
} else {
return "whatsapp://send?phone=$phone&text=${Uri.encodeFull(message)}";
}
}
if (await canLaunch(url())) {
await launch(url());
} else {
_dialog.showDialog(description: 'Отсутсвует приложение WhatsApp');
}
}
void showFloatingActionButton(bool value) {
setState(() {
showFab = value;
});
}
}