253 lines
9.2 KiB
Dart
253 lines
9.2 KiB
Dart
import 'package:flutter/material.dart';
|
||
import 'package:logger/logger.dart';
|
||
import 'package:satu/core/models/dialog_models.dart';
|
||
import 'package:satu/core/models/dictionary/category/category_response.dart';
|
||
import 'package:satu/core/models/dictionary/good/good_response_entity.dart';
|
||
import 'package:satu/core/services/dialog_service.dart';
|
||
import 'package:satu/core/services/dictionary_service.dart';
|
||
import 'package:satu/core/services/navigator_service.dart';
|
||
import 'package:satu/core/utils/locator.dart';
|
||
import 'package:satu/core/utils/logger.dart';
|
||
import 'package:satu/core/utils/utils_parse.dart';
|
||
import 'package:satu/routes/route_names.dart';
|
||
import 'package:satu/shared/ui_helpers.dart';
|
||
import 'package:satu/widgets/bar/products_app_bar.dart';
|
||
import 'package:satu/widgets/buttons/busy_button.dart';
|
||
import 'package:satu/widgets/fields/input_field.dart';
|
||
import 'package:satu/widgets/fields/line_tile.dart';
|
||
|
||
class GoodEdit extends StatefulWidget {
|
||
const GoodEdit({
|
||
required this.good,
|
||
Key? key,
|
||
}) : super(key: key);
|
||
final GoodResponseEntity good;
|
||
|
||
@override
|
||
_GoodEditState createState() => _GoodEditState();
|
||
}
|
||
|
||
class _GoodEditState extends State<GoodEdit> {
|
||
final NavigatorService _navigatorService = locator<NavigatorService>();
|
||
final DictionaryService _dictionaryService = locator<DictionaryService>();
|
||
final DialogService _dialogService = locator<DialogService>();
|
||
final Logger log = getLogger('_GoodEditState');
|
||
late TextEditingController _controllerArticle;
|
||
late TextEditingController _controllerName;
|
||
|
||
late TextEditingController _controllerPrice;
|
||
late TextEditingController _controllerOptPrice;
|
||
late TextEditingController _controllerBasePrice;
|
||
late TextEditingController _controllerEan;
|
||
late TextEditingController _controllerDescription;
|
||
|
||
bool isDivisible = false;
|
||
|
||
String? parentCategoryName;
|
||
int? parentCategoryId;
|
||
|
||
@override
|
||
void initState() {
|
||
super.initState();
|
||
if (widget.good.categoryId != null) {
|
||
parentCategoryId = widget.good.categoryId;
|
||
parentCategoryName = widget.good.categoryName;
|
||
}
|
||
_controllerArticle =
|
||
TextEditingController(text: widget.good.articul?.toString() ?? '');
|
||
_controllerName = TextEditingController(text: widget.good.name);
|
||
_controllerPrice = TextEditingController(
|
||
text:
|
||
widget.good.price != null ? formatDecimal(widget.good.price!) : '');
|
||
_controllerOptPrice = TextEditingController(
|
||
text: widget.good.optPrice != null
|
||
? formatDecimal(widget.good.optPrice!)
|
||
: '');
|
||
_controllerBasePrice = TextEditingController(
|
||
text: widget.good.basePrice != null
|
||
? formatDecimal(widget.good.basePrice!)
|
||
: '');
|
||
_controllerEan = TextEditingController(text: widget.good.ean13);
|
||
_controllerDescription =
|
||
TextEditingController(text: widget.good.description);
|
||
}
|
||
|
||
@override
|
||
void dispose() {
|
||
_controllerArticle.dispose();
|
||
_controllerName.dispose();
|
||
_controllerPrice.dispose();
|
||
_controllerOptPrice.dispose();
|
||
_controllerBasePrice.dispose();
|
||
_controllerEan.dispose();
|
||
_controllerDescription.dispose();
|
||
super.dispose();
|
||
}
|
||
|
||
void save() async {
|
||
GoodResponseEntity good = widget.good;
|
||
good.name = _controllerName.text;
|
||
good.price = parseNumeric(_controllerPrice.text);
|
||
good.optPrice = parseNumeric(_controllerOptPrice.text);
|
||
good.basePrice = parseNumeric(_controllerBasePrice.text);
|
||
good.ean13 = _controllerEan.text;
|
||
good.description = _controllerDescription.text;
|
||
String? message = await _dictionaryService.saveGood(good);
|
||
if (message != null) {
|
||
_dialogService.showDialog(description: message);
|
||
} else {
|
||
_navigatorService.pop(true);
|
||
}
|
||
}
|
||
|
||
void delete() async {
|
||
GoodResponseEntity good = widget.good;
|
||
String? message = await _dictionaryService.deleteGood(good);
|
||
if (message != null) {
|
||
_dialogService.showDialog(description: message);
|
||
} else {
|
||
_navigatorService.pop(true);
|
||
}
|
||
}
|
||
|
||
@override
|
||
Widget build(BuildContext context) {
|
||
return Scaffold(
|
||
appBar: ProductsAppBar(
|
||
title: widget.good.id == null
|
||
? 'Создание товара'
|
||
: 'Редактирование товара',
|
||
),
|
||
body: SingleChildScrollView(
|
||
physics: const BouncingScrollPhysics(),
|
||
child: Column(
|
||
crossAxisAlignment: CrossAxisAlignment.start,
|
||
children: [
|
||
verticalSpaceSmall,
|
||
InputField(
|
||
isReadOnly: true,
|
||
controller: _controllerArticle,
|
||
labelText: 'Номенклатурный номер',
|
||
placeholder: 'Не присвоен',
|
||
),
|
||
LineTile(
|
||
parentCategoryName ?? '',
|
||
onTap: selectCategory,
|
||
labelText: 'Категория',
|
||
placeholder: 'Выберите категорию',
|
||
),
|
||
verticalSpaceSmall,
|
||
InputField(
|
||
controller: _controllerName,
|
||
labelText: 'Наименование',
|
||
placeholder: 'Введите наименование товара',
|
||
enterPressed: (){
|
||
FocusManager.instance.primaryFocus?.unfocus();
|
||
},
|
||
textInputAction: TextInputAction.done,
|
||
),
|
||
InputField(
|
||
controller: _controllerPrice,
|
||
labelText: 'Розничная цена',
|
||
placeholder: 'Введите розничную цену',
|
||
suffixText: '₸',
|
||
textInputType:
|
||
const TextInputType.numberWithOptions(decimal: true),
|
||
enterPressed: (){
|
||
FocusManager.instance.primaryFocus?.unfocus();
|
||
},
|
||
textInputAction: TextInputAction.done,
|
||
),
|
||
InputField(
|
||
controller: _controllerOptPrice,
|
||
labelText: 'Оптовая цена',
|
||
placeholder: 'Введите оптовую цену',
|
||
suffixText: '₸',
|
||
textInputType:
|
||
const TextInputType.numberWithOptions(decimal: true),
|
||
enterPressed: (){
|
||
FocusManager.instance.primaryFocus?.unfocus();
|
||
},
|
||
textInputAction: TextInputAction.done,
|
||
),
|
||
InputField(
|
||
controller: _controllerBasePrice,
|
||
labelText:
|
||
'Закупочная цена для автоматически пополняемого товара',
|
||
placeholder: 'Введите закупочную цену',
|
||
suffixText: '₸',
|
||
textInputType:
|
||
const TextInputType.numberWithOptions(decimal: true),
|
||
enterPressed: (){
|
||
FocusManager.instance.primaryFocus?.unfocus();
|
||
},
|
||
textInputAction: TextInputAction.done,
|
||
),
|
||
InputField(
|
||
controller: _controllerEan,
|
||
labelText: 'EAN Штрих-код',
|
||
placeholder: 'Введите EAN',
|
||
textInputType:
|
||
const TextInputType.numberWithOptions(decimal: false),
|
||
enterPressed: (){
|
||
FocusManager.instance.primaryFocus?.unfocus();
|
||
},
|
||
textInputAction: TextInputAction.done,
|
||
),
|
||
InputField(
|
||
controller: _controllerDescription,
|
||
labelText: 'Описание',
|
||
placeholder: 'Введите описание товара',
|
||
multiline: true,
|
||
textInputType: TextInputType.multiline,
|
||
enterPressed: (){
|
||
FocusManager.instance.primaryFocus?.unfocus();
|
||
},
|
||
textInputAction: TextInputAction.done,
|
||
),
|
||
Padding(
|
||
padding:
|
||
const EdgeInsets.symmetric(horizontal: 45.0, vertical: 20.0),
|
||
child: BusyButton(title: 'СОХРАНИТЬ', onPressed: () {
|
||
save();
|
||
}),
|
||
),
|
||
if (widget.good.id != null)
|
||
Padding(
|
||
padding: const EdgeInsets.symmetric(
|
||
horizontal: 45.0, vertical: 20.0),
|
||
child: BusyButton(
|
||
title: 'УДАЛИТЬ',
|
||
onPressed: () async {
|
||
DialogResponse response =
|
||
await _dialogService.showConfirmationDialog(
|
||
title: 'Внимание',
|
||
description:
|
||
'Вы уверены, что хотите удалить категорию?',
|
||
confirmationTitle: 'Удалить',
|
||
cancelTitle: 'Отмена');
|
||
|
||
if(response.confirmed){
|
||
delete();
|
||
}
|
||
},
|
||
isDanger: true,
|
||
),
|
||
),
|
||
],
|
||
),
|
||
),
|
||
);
|
||
}
|
||
|
||
Future<void> selectCategory() async {
|
||
final dynamic result =
|
||
await _navigatorService.push(categorySelectViewRoute);
|
||
CategoryResponse? category = result as CategoryResponse?;
|
||
setState(() {
|
||
parentCategoryId = category?.id;
|
||
parentCategoryName = category?.name;
|
||
});
|
||
}
|
||
}
|