Проведение покупки, проверка деактивированного токена, подтверждение логаута, функциональная маска на сканере, кнопка назад в faq

This commit is contained in:
Ivan Murashov
2017-07-26 18:57:29 +03:00
parent 313dc307dc
commit 73e139f925
10 changed files with 226 additions and 112 deletions

View File

@@ -42,7 +42,7 @@ class _RegistrationScreenState extends BaseState<FinishRegistrationScreen> {
if (_tokenActive) {
startScanner(context);
} else {
checkToken(context).then((response) {
checkTokenStatus(context).then((response) {
print(response.body);
Map parsedMap = JSON.decode(response.body);

View File

@@ -2,6 +2,7 @@ import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'main.dart';
import 'base_state.dart';
/// Класс содержит заголовки и текст блоков FAQ.
class Entry {
@@ -33,24 +34,22 @@ class EntryItem extends StatelessWidget {
}
}
/// Экран проведения покупки.
class FAQScreen extends StatelessWidget {
class FAQScreen extends StatefulWidget {
@override State createState() => new FAQScreenState<FAQScreen>();
}
AppBar getAppBar(BuildContext context) {
return new AppBar(title: new Text('FAQ', style: new TextStyle(fontSize: 18.0)),
backgroundColor: primaryColor, actions: <Widget>[getLogoutButton(context)]);
class FAQScreenState<T> extends BaseState<FAQScreen> {
@override String getTitle() {
return "FAQ";
}
getLogoutButton(BuildContext context) {
return new IconButton(icon: new Image.asset(logout_png, height: iconHeight, width: iconHeight), onPressed: () => logout(context));
}
@override
Widget build(BuildContext context) {
return new MaterialApp(home: new Scaffold(appBar: getAppBar(context), body: getBody()));
@overide getMenuButtons(BuildContext context) {
return <Widget>[getLogoutButton()];
}
/// Метод возвращает ListView с блоками faq.
getBody() {
@override Widget getScreenContent() {
return new ListView.builder(
itemBuilder: (BuildContext context, int index) => new EntryItem(data[index]),
itemCount: data.length);
@@ -64,8 +63,6 @@ class FAQScreen extends StatelessWidget {
new Entry('ОБЩАЯ ИНФОРМАЦИЯ', commonGuide)
];
/// TODO: Отформатировать строки
static const String registrationGuide = '''После запуска приложения вы окажетесь на странице регистрации магазина.
Введите DIN код магазина (выдается партнером/менеджером International Auto Club, дублируется на почту)
Нажать кнопку: «Зарегистрировать»

View File

@@ -55,10 +55,28 @@ void main() {
}
/// Проверка статуса токена. Токен может быть активирован, либо не активирован.
checkToken(BuildContext context) async {
checkTokenStatus(BuildContext context) async {
return httpClient.get(intUrl + 'tokens/' + token + '?_dmapptoken=' + intToken);
}
createToken(String merchantId) async {
String url = intUrl + 'tokens/?_dmapptoken=' + intToken;
String posID = await platform.invokeMethod('getPosID');
print('posID: ${posID}');
print('merchantId: ${merchantId}');
// Поле description - необязательное.
var body = {
'merchant_shop': merchantId,
'pos': posID,
};
return httpClient.post(url, body: body);
}
/// Запуск спецефичной для каждой платформы части приложения - сканера.
/// Может производиться с нескольких экранов (splash, finish_registration).
startScanner(BuildContext context) async {
@@ -88,7 +106,7 @@ startScanner(BuildContext context) async {
print(response.body);
List usersList = JSON.decode(response.body);
print('usersList.length: ${usersList.length}');
if (usersList.length > 0) {
pushRoute(context, new PurchaseScreen(usersList[0], card));
}
@@ -105,21 +123,38 @@ startScanner(BuildContext context) async {
}
logout(BuildContext context) {
if (token != null) {
String url = intUrl + 'tokens/' + token + '?_dmapptoken=' + intToken;
print(url);
httpClient.delete(url).then((response) {
print(response.body);
const platform = const MethodChannel('com.dinect.checker/instance_id');
platform.invokeMethod('removeKeys');
Navigator.of(context).pop();
pushRoute(context, new RegistrationScreen());
}).catchError((error) {
print(error.toString());
});
} else {
Navigator.of(context).pop();
}
showDialog(context: context, child: new AlertDialog(
title: new Text('Подтверждение'),
content: new Text('Вы действительно хотите выйти и ввести другой номер магазина?'),
actions: <Widget>[
new FlatButton(
child: new Text('Нет'),
onPressed: () {
Navigator.of(context).pop();
}
),
new FlatButton(
child: new Text('Да'),
onPressed: () {
if (token != null) {
String url = intUrl + 'tokens/' + token + '?_dmapptoken=' + intToken;
print(url);
httpClient.delete(url).then((response) async {
print(response.body);
await platform.invokeMethod('removeKeys');
Navigator.of(context).pop();
Navigator.of(context).pop();
pushRoute(context, new RegistrationScreen());
}).catchError((error) {
print(error.toString());
});
} else {
Navigator.of(context).pop();
Navigator.of(context).pop();
}
}
)]));
}
/// Навигация по приложению.

View File

@@ -27,7 +27,7 @@ class PurchaseScreenState<T> extends BaseState<PurchaseScreen> {
}
Map user;
String card;
String card = '';
String integerPart = '', fractionalPart = '';
String loyality = '';
@@ -40,7 +40,7 @@ class PurchaseScreenState<T> extends BaseState<PurchaseScreen> {
getValueWithTitle('Вознаграждение', loyality),
getHintLabel(),
getDecoratedTextWidget(),
buildButton(new EdgeInsets.only(top: 36.0, left: buttonVerticalMargin, right: buttonVerticalMargin), buildRaisedButton(context, 'ЗАВЕРШИТЬ ПОКУПКУ', () => _purchase(context))),
buildButton(new EdgeInsets.only(top: 36.0, left: buttonVerticalMargin, right: buttonVerticalMargin), buildRaisedButton(context, 'ЗАВЕРШИТЬ ПОКУПКУ', () => onPurchaseClick(context))),
buildButton(new EdgeInsets.only(top: 24.0, left: buttonVerticalMargin, right: buttonVerticalMargin), buildFlatButton(context, 'СКАНИРОВАТЬ', primaryColor))])
].reversed.toList()));
}
@@ -123,7 +123,7 @@ class PurchaseScreenState<T> extends BaseState<PurchaseScreen> {
return temporaryInteger + '.' + temporaryFractional;
}
_purchase(BuildContext context) {
onPurchaseClick(BuildContext context) {
String val = _buildSum();
print(val);
showDialog(context: context, child: new AlertDialog(
@@ -139,10 +139,39 @@ class PurchaseScreenState<T> extends BaseState<PurchaseScreen> {
new FlatButton(
child: new Text('Да'),
onPressed: () {
Navigator.of(context).pop();
pushRoute(context, new PurchaseSuccessScreen(val, user['first_name']));
purchase(val);
},
)
]));
}
purchase(String sum_total) {
platform.invokeMethod('getDocID').then((result) {
String url = user['purchases_url'];
var body = {
'doc_id': result,
'curr_iso_code': '643',
'commit': 'true',
'sum_total': sum_total
};
var headers = {
'DM-Authorization': 'dmapptoken 9fec83cdca38c357e6b65dbb17514cdd36bf2a08',
'Authorization': 'dmtoken ${token}'
};
httpClient.post(url, body: body, headers: headers).then((response) {
print(response.body);
Navigator.of(context).pop();
pushRoute(context, new PurchaseSuccessScreen(sum_total, user['first_name']));
}).catchError((error) {
print(error.toString());
});
});
}
}

View File

@@ -54,22 +54,13 @@ class _RegistrationScreenState extends BaseState<RegistrationScreen> {
/// Получение от платформы id установки, формирование запроса на получение токена, сохранение токена.
_register(BuildContext context) async {
String url = intUrl + 'tokens/?_dmapptoken=' + intToken;
String pos = (new DateTime.now().millisecondsSinceEpoch / 1000).toString();
// Поле description - необязательное.
var body = {
'merchant_shop': textFieldValue,
'pos': pos,
};
httpClient.post(url, body: body).then((response) {
createToken(textFieldValue).then((response) {
setState(() {
error = null;
loading = false;
});
print(response.body);
Map parsedMap = JSON.decode(response.body);
if (response.statusCode == 201) {

View File

@@ -42,27 +42,50 @@ class SplashScreen extends StatelessWidget {
pushRoute(context, new RegistrationScreen());
} else {
checkToken(context).then((response) {
print(response.body);
Map parsedMap = JSON.decode(response.body);
bool active = parsedMap['active'];
if (active) {
// Запускается экран сканера, токен кассы активирован, с его помощью можно делать запросы к pos-api.
startScanner(context);
} else {
// Запускается экран ожидания активации токена.
// В реальности токен активируется в админке вручную,
// на тестовом сервере токен активируется через несколько минут после создания.
pushRoute(context, new FinishRegistrationScreen());
}
checkTokenStatus(context).then((statusResponse) {
handleStatusResponse(context, statusResponse);
}).catchError((error) {
print('Handle exception!');
print(error.toString());
return false;
});
}
}
startRegistration() async {
}
handleStatusResponse(BuildContext context, var statusResponse) async {
int code = statusResponse.statusCode;
print('resp: ${code}');
if (code == 404) {
platform.invokeMethod('removeKeys').then((result) {
print('try to start registration');
pushRoute(context, new RegistrationScreen());
});
} else {
Map statusResponseMap = JSON.decode(statusResponse.body);
bool active = statusResponseMap['active'];
if (active) {
startScanner(context);
} else {
createToken(await platform.invokeMethod('getMerchantID')).then((response) {
print('response.body: ${response.body}');
if (response.statusCode == 409) {
pushRoute(context, new FinishRegistrationScreen());
} else {
startRegistration();
}
}).catchError((error) {
platform.invokeMethod('removeKeys').then((result) => pushRoute(context, new RegistrationScreen()));
});
}
}
}
}