Files
checker/lib/screens/purchase.dart
2018-03-11 12:48:45 +03:00

441 lines
13 KiB
Dart

import 'package:checker/base/base_screen.dart';
import 'package:checker/db.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'dart:convert';
import 'dart:core';
import 'dart:async';
import 'package:checker/resources.dart';
import 'package:checker/strings.dart';
import 'package:checker/common.dart';
import 'package:checker/consts.dart';
import 'package:checker/network.dart';
import 'package:checker/base/base_state.dart';
import 'package:checker/screens/purchase_success.dart';
/// Экран проведения покупки.
class PurchaseScreen extends BaseScreen {
PurchaseScreen(helper, app, this.user, this.card) : super(helper, app);
final String user;
final String card;
@override
State createState() => new PurchaseScreenState<PurchaseScreen>(helper, app, user, card);
}
class PurchaseScreenState<T> extends BaseState<PurchaseScreen> {
/// Объект, помогающий вручную изменять введенный пользователем текст.
/// Используется для форматирования введенных пользователем данных
/// (удаляет запрещенные символы до их отображаения).
TextEditingController controller = new TextEditingController();
TextEditingController bonusController = new TextEditingController();
FocusNode _focusNodeSum = new FocusNode();
FocusNode _focusNodeBonus = new FocusNode();
bool isAutomaticallyImplyLeading() => false;
PurchaseScreenState(SqliteHelper helper, String app, String userString, String card) : super(helper, app) {
this.user = JSON.decode(userString);
this.card = card;
}
@override
void initState() {
loading = true;
requestAsyncData(user);
super.initState();
}
@override
Widget build(BuildContext ctx) {
return getMainWidget();
}
bool purchaseInProgress = false;
Map user;
String card = '';
String loyalityType = '';
String loyalty = '';
String bonus = '';
List<Map> coupons = [];
@override
Widget getScreenContent() {
List<Widget> widgetList = [];
widgetList.add(getValueWithDescription(
StringsLocalization.buyer(),
user['first_name'] == null ? '' : user['first_name']
));
widgetList.add(getValueWithDescription(StringsLocalization.card(), card));
if (app != 'crypto') { // FIXME Заменить на crypto
widgetList.add(getValueWithDescription(StringsLocalization.reward(), loyalty));
}
if (bonus.length > 0) {
widgetList.add(getValueWithDescription(StringsLocalization.bonus(), bonus));
}
widgetList.add(getHintLabel());
widgetList.add(getInputField()); // Нельзя добавить еще одно поле таким же способом
if (app != 'autobonus') {
if (this.loyalityType == 'bonus') {
widgetList.add(getBonusInputField());
}
if (this.coupons.length > 0) {
widgetList.add(getItemTitle(StringsLocalization.selectCoupons()));
this.coupons.forEach((couponItem) {
widgetList.add(getItemToggleSwitch(
couponItem['offer_name'],
couponItem['coupon_condition'],
couponItem['isSet'],
(val) {
setState(() {
couponItem['isSet'] = val;
});
}
));
});
}
}
widgetList.add(wrapButton(getScreenMargins(36.0), getCompleteButton()));
widgetList.add(wrapButton(
getScreenMargins(24.0),
getScanButton(
context,
StringsLocalization.scan(),
Resources.getPrimaryColor(app)
)
));
return new Column(children: <Widget>[
new Expanded(
child: new ListView(children: widgetList))
]);
}
getBonusInputField() {
var bonusTextField = new EnsureVisibleWhenFocused(
focusNode: _focusNodeBonus,
child: new TextField(
focusNode: _focusNodeBonus,
keyboardType: TextInputType.number,
decoration: new InputDecoration.collapsed(
hintText: StringsLocalization.bonusHint(),
hintStyle: new TextStyle(color: greyTextColor, fontSize: 16.0)
),
controller: bonusController,
onSubmitted: (String text) {
setState(() {
bonusController.text = text;
});
},
textAlign: TextAlign.center,
));
return new Column(
children: <Widget>[
new Container(
margin: new EdgeInsets.only(
left: verticalMargin,
right: verticalMargin,
top: verticalMargin
),
padding: getInputFieldContainerPadding(),
decoration: getInputFieldContainerDecoration(),
child: bonusTextField
),
new Container(
margin: new EdgeInsets.only(
top: 5.0
),
child: new Text(
StringsLocalization.bonusExplanation(),
textAlign: TextAlign.center,
overflow: TextOverflow.ellipsis,
style: new TextStyle(color: greyTextColor, fontSize: 11.0),
)
)
],
);
}
getScreenMargins(double top) {
double side = 42.0;
return new EdgeInsets.only(top: top, left: side, right: side);
}
getCompleteButton() {
return buildRaisedButton(
StringsLocalization.completePurchase(), () => onPurchaseClick());
}
Widget getScanButton(BuildContext context, String title, Color textColor) {
return new Container(
height: buttonHeight,
child: new FlatButton(
child: new Text(title, style: new TextStyle(color: textColor)),
onPressed: () => Navigator.of(context).pop()),
decoration: new BoxDecoration(
border: new Border.all(
color: Resources.getButtonColor(app), width: 1.0),
borderRadius: new BorderRadius.all(new Radius.circular(4.0))));
}
@override
String getTitle() {
return StringsLocalization.carryingPurchase();
}
@override
getHintString() {
return StringsLocalization.sum();
}
@override
getTextWidget() {
// ?? TODO переделать, т.к. позволяет иметь только одно поле ввода на странице
return new EnsureVisibleWhenFocused(
focusNode: _focusNodeSum,
child: new TextField(
focusNode: _focusNodeSum,
keyboardType: TextInputType.number,
decoration: new InputDecoration.collapsed(
hintText: getHintString(),
hintStyle: new TextStyle(color: greyTextColor, fontSize: 16.0)),
controller: controller,
onSubmitted: (String text) {
setState(() {
controller.text = _parseSum(text);
});
},
textAlign: TextAlign.center,
autofocus: true
));
}
requestAsyncData(Map user) async {
bool showBonus = await platform.invokeMethod('showBonus');
if (await platform.invokeMethod('isOnline')) {
var response, couponResponse;
print(user['coupons_url']);
try {
var token = await helper.getToken();
response = await getLoyaltyRequest(user['loyalty_url'], token);
couponResponse = await getCouponsRequest(
user['coupons_url'] + '?status=ACTIVE',
token
);
} catch(error) {
print(error.toString());
}
Map loyality = JSON.decode(response.body);
Map coupons = JSON.decode(couponResponse.body);
coupons['results'].forEach((couponItem) {
couponItem['isSet'] = false;
});
setState(() {
loading = false;
this.coupons = coupons['results'];
this.loyalityType = loyality['type'];
setBonuses(loyality, showBonus);
});
}
}
// TODO: Переделать, если потребуется
String _cleanupNumber(String text) {
String tmp = text
.replaceAll(' ', '')
.replaceAll('-', '')
.replaceAll(',', '.')
.replaceAll('..', '.');
while (tmp.indexOf('..') != -1) {
tmp = tmp.replaceAll('..', '.');
}
return tmp;
}
_parseSum(String input) {
num sumTotal = 0.0;
String text = _cleanupNumber(input);
try {
sumTotal = num.parse(text);
} catch (exception) {
print(exception);
try {
int idx = text.indexOf('.');
String integerPart = text.substring(0, idx);
String fractionalPart = text.substring(idx + 1, text.length);
if (fractionalPart.length > 2) {
fractionalPart = fractionalPart.substring(0, 2);
}
return '$integerPart.$fractionalPart';
} catch (exception) {
print(exception);
}
}
print(sumTotal.toStringAsFixed(2));
return sumTotal.toStringAsFixed(2);
}
onPurchaseClick() {
String val = _parseSum(controller.text);
helper.getCurrency().then((currency) {
print(currency.toString());
showDialog(
context: context,
child: new AlertDialog(
title: new Text(StringsLocalization.confirmation()),
content:
new Text(
StringsLocalization.confirmPurchase(val, currency)
),
actions: <Widget>[
new FlatButton(
child: new Text(StringsLocalization.no()),
onPressed: () {
Navigator.of(context).pop();
},
),
new FlatButton(
child: new Text(StringsLocalization.yes()),
onPressed: () {
Navigator.of(context).pop();
purchase(val);
},
)
]));
});
}
apiErrorAlert(String errorText) {
showDialog(
context: context,
child: new AlertDialog(
content: new Text(errorText),
actions: <Widget>[
new FlatButton(
child: new Text('Ok'),
onPressed: () {
Navigator.of(context).pop();
},
)
]
)
);
}
purchase(String sumTotal) async {
setState(() {
loading = true;
});
if (await platform.invokeMethod('isOnline')) {
if (!purchaseInProgress) {
purchaseInProgress = true;
String token = await helper.getToken();
var result = await helper.getMerchantID();
var currency = await helper.getCurrency();
var couponIds = [];
this.coupons.forEach((item) {
if (item['isSet'] == true) couponIds.add(item['id']);
});
print(couponIds);
var body = {
'doc_id': result,
'curr_iso_code': currency.toString(),
'commit': 'true',
'sum_total': sumTotal,
};
if (bonusController.text.length > 0) {
body['bonus_payment'] = bonusController.text;
}
if (couponIds.length > 0) {
body['coupons'] = couponIds.join(",");
}
var purchaseResponse;
Map purchase;
try {
purchaseResponse = await getPurchaseRequest(user['purchases_url'], body, token);
purchase = JSON.decode(purchaseResponse.body);
} catch(error) {
purchaseInProgress = false;
print(error.toString());
}
if (purchase.containsKey('errors')) {
List<String> errors = purchase['errors'];
purchaseInProgress = false;
apiErrorAlert(errors[0]);
} else {
var couponsResponse;
try {
couponsResponse = await getCouponsRequest(purchase['coupons_url'], token);
print(couponsResponse.body);
} catch(error) {
purchaseInProgress = false;
print(error.toString());
}
Map coupons = JSON.decode(couponsResponse.body);
new Future.delayed(const Duration(milliseconds: 200), () {
print('show purchase success!');
var route = new MaterialPageRoute<Null>(builder: (BuildContext context) => new PurchaseSuccessScreen(
sumTotal,
user['first_name'] == null ? '' : user['first_name'],
helper,
app,
purchase,
coupons['results']
), fullscreenDialog: true);
Navigator.of(context).push(route).then((_) {
Navigator.of(context).pop();
});
});
}
}
}
}
void setBonuses(Map bonuses, bool showBonus) {
print('kifio ' + this.loyalityType);
if (bonuses['type'] == 'amount') {
this.loyalty = '${user['discount']}%';
} else {
double loyaltyVal = (double.parse(bonuses['amount_to_bonus'][1]) /
bonuses['amount_to_bonus'][0]) * 100;
this.loyalty = '${loyaltyVal.toStringAsFixed(0)}%';
}
if (showBonus && (this.loyalityType == 'bonus')) {
this.bonus = '${user['bonus']}';
}
print('kifio ' + this.loyalty);
print('bonus ' + this.bonus);
}
}