Files
checker/lib/registration.dart

183 lines
7.3 KiB
Dart
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import 'dart:convert'; // Пакет для обработки json с ответом от сервера.
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'main.dart';
import 'dart:async';
import 'activate_token.dart';
/// На фото мой сын, большой любитель голых констант.
/// Экран регистрации магазина и кассы.
class RegistrationScreen extends StatefulWidget {
@override State createState() => new _RegistrationScreenState();
}
class _RegistrationScreenState extends State<RegistrationScreen> {
String error = null;
bool _loading = false;
@override build(BuildContext context) {
return new Scaffold(appBar: _getAppBar(), body: _getScreen(context));
}
_getAppBar() {
return new AppBar(title: new Text("Регистрация"),
actions: <Widget>[new IconButton(icon: new Icon(Icons.help_outline), onPressed: () {})]);
}
_getScreen(BuildContext context) {
return new Stack(children: <Widget>[_getScreenContent(), _getProgressIndicator()]);
}
/// Высота контейнера задана для того, чтобы элементы располагались вверху экрана
/// и список скроллился снизу вверх при открытии клавиатуры.
_getScreenContent() {
return new Container(height: 332.0,
child: new ListView(reverse: true, children: <Widget>[
new Center(child: new Column(children: <Widget>[
_getLogo(),
_getMerchantIDTitle(),
_getDecoratedInputField(),
_getButton(context)]))
].reversed.toList()));
}
/// Индикация отправки токена кассы.
_getProgressIndicator() {
return new Center(child: _loading ? new CircularProgressIndicator() : null);
}
/// Метод возвращает контейнер с отступами, который содержит картинку с логотипом.
/// Картинка должна
_getLogo() {
double containerHeight = 162.0;
double imageHeight = 24.0;
double imageWidth = 156.0;
return new Container(height: containerHeight, child: new Image.asset(logo_png, height: imageHeight, width: imageWidth));
}
_getMerchantIDTitle() {
return new Container(margin: new EdgeInsets.only(top: 8.0, bottom: 8.0, left: 28.0, right: 28.0),
child: new Row(crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[new Container(padding: new EdgeInsets.only(right: 8.0), child: new Text(_getMerchantIDTitleText(), overflow: TextOverflow.ellipsis, textAlign: TextAlign.left,
style: new TextStyle(fontWeight: FontWeight.w300, color: error == null ? greyTextColor : primaryColor, fontSize: 14.0)))]));
}
_getMerchantIDTitleText() {
if (merchantID.length == 0 && error == null) {
return ' ';
} else if (error != null) {
return error;
} else {
return 'ID Магазина';
}
}
/// Метод возвращает контейнер с установленными отступами, в котором размещен TextField обернутый в BoxDecoration.
_getDecoratedInputField() {
double margin = 28.0;
double verticalPadding = 12.0;
double horizontalPadding = 16.0;
return new Container(margin: new EdgeInsets.only(left: margin, right: margin),
padding: new EdgeInsets.only(top: verticalPadding, bottom: verticalPadding, left: horizontalPadding, right: horizontalPadding),
decoration: _getDecoraionForInputField(),
child: _getInputField());
}
/// Метод возвращает TextField для _getDecoratedInputField
_getInputField() {
return new TextField(keyboardType: TextInputType.number, decoration: new InputDecoration.collapsed(hintText: merchantIDHint,
hintStyle: new TextStyle(color: greyTextColor, fontSize: 16.0)),
onChanged: (text) => _handleUserInput(text));
}
/// Метод возвращает BoxDecoration для _getDecoratedInputField
_getDecoraionForInputField() {
return new BoxDecoration(color: textFieldBackground,
border: new Border.all(color: textBorderColor, width: 1.0,),
borderRadius: new BorderRadius.all(new Radius.circular(4.0)));
}
/// Метод возвращает кнопку, которая запускает отправку токена кассы на сервер.
_getButton(BuildContext context) {
double buttonHeight = 42.0;
double topMargin = 36.0;
double horizontalPadding = 40.0; // Отступы по краям от кнопки.
return new Container(margin: new EdgeInsets.only(top: topMargin), height: buttonHeight,
padding: new EdgeInsets.only(left: horizontalPadding, right: horizontalPadding),
child: new RaisedButton(child: new Text('ЗАРЕГИСТРИРОВАТЬ',
style: new TextStyle(color: Colors.white)),
onPressed: _isValidMerchantID() && !_loading ? () => _registerShop(context) : null,
color: primaryColor));
}
/// Токен кассы - это DIN код. DIN код - это специальный код динекта, максимальная его длина - 25 символов.
_isValidMerchantID() {
return merchantID.length > 0 && merchantID.length < 25;
}
/// Смена состояния экрана при изменении текста в поле ввода.
_handleUserInput(String text) {
setState(() {
merchantID = text;
});
}
/// Показать индикатор, запросить токен.
_registerShop(BuildContext context) {
setState(() {
_loading = true;
_register(context);
});
}
/// Экран зависает на 1 сек, после этого выполняется переход на экран потверждения токена.
_registerDemo(BuildContext context) {
new Future.delayed(const Duration(milliseconds: 1000), () {
_loading = false;
pushRoute(context, new FinishRegistrationScreen());
});
}
/// Получение от платформы id установки, формирование запроса на получение токена, сохранение токена.
_register(BuildContext context) async {
const platform = const MethodChannel('com.dinect.checker/instance_id');
String url = intUrl + 'tokens/?_dmapptoken=' + intToken;
String pos = (new DateTime.now().millisecondsSinceEpoch / 1000).toString();
// Поле description - необязательное.
var body = {
'merchant_shop': merchantID,
'pos': pos,
};
httpClient.post(url, body: body).then((response) {
setState(() {
error = null;
});
print(response.body);
Map parsedMap = JSON.decode(response.body);
setState(() {
_loading = false;
});
if (response.statusCode == 201) {
token = parsedMap['token'];
platform.invokeMethod('saveToken', {'token' : token});
platform.invokeMethod('saveMerchantID', {'merchantID' : merchantID});
pushRoute(context, new FinishRegistrationScreen());
} else {
setState(() {
error = parsedMap['errors'][0];
});
}
}).catchError((error) {
setState(() {
error = 'Отсутствует интернет соединение';
});
});
}
}