parent
1f502f8493
commit
3be37e5057
|
|
@ -0,0 +1,10 @@
|
|||
class CategoryRowDao {
|
||||
CategoryRowDao(this.name, this.parentName, this.id,
|
||||
{this.parentId = 0, this.ean});
|
||||
|
||||
final String name;
|
||||
final String parentName;
|
||||
final String? ean;
|
||||
final int? id;
|
||||
final int? parentId;
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
class GoodRowDao {
|
||||
GoodRowDao(this.name, this.categoryName,
|
||||
{this.ean, this.id, this.categoryId}
|
||||
);
|
||||
|
||||
final String name;
|
||||
final String categoryName;
|
||||
final int? categoryId;
|
||||
final String? ean;
|
||||
final int? id;
|
||||
}
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
import 'dart:convert';
|
||||
import 'dart:convert';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:satu/core/base/base_service.dart';
|
||||
|
|
|
|||
|
|
@ -26,7 +26,8 @@ class DbService extends BaseService {
|
|||
|
||||
// this opens the database (and creates it if it doesn't exist)
|
||||
Future<Database> _initDatabase() async {
|
||||
final Directory documentsDirectory = await getApplicationDocumentsDirectory();
|
||||
final Directory documentsDirectory =
|
||||
await getApplicationDocumentsDirectory();
|
||||
final String path = join(documentsDirectory.path, _databaseName);
|
||||
final Database db = await openDatabase(path,
|
||||
version: _databaseVersion, onUpgrade: _onUpdate, onCreate: _onCreate);
|
||||
|
|
@ -100,22 +101,27 @@ class DbService extends BaseService {
|
|||
return result;
|
||||
}
|
||||
|
||||
Future<List<Map<String, dynamic>>> queryRaw(String sql, List<dynamic> args) async {
|
||||
Future<List<Map<String, dynamic>>> queryRaw(
|
||||
String sql, List<dynamic> args) async {
|
||||
final Database db = await instance.database;
|
||||
final List<Map<String, dynamic>> result = await db.rawQuery(sql, args );
|
||||
final List<Map<String, dynamic>> result = await db.rawQuery(sql, args);
|
||||
return result;
|
||||
}
|
||||
|
||||
Future<List<Map<String, dynamic>>> queryAllRowsOrderBy(String table, String orderBy) async {
|
||||
Future<List<Map<String, dynamic>>> queryAllRowsOrderBy(
|
||||
String table, String orderBy) async {
|
||||
final Database db = await instance.database;
|
||||
final List<Map<String, dynamic>> result = await db.query(table, orderBy: orderBy);
|
||||
final List<Map<String, dynamic>> result =
|
||||
await db.query(table, orderBy: orderBy);
|
||||
return result;
|
||||
}
|
||||
|
||||
Future<List<Map<String, dynamic>>> queryRowsWithWhere(
|
||||
String table, String where, List<dynamic> args, { String? orderBy }) async {
|
||||
String table, String where, List<dynamic> args,
|
||||
{String? orderBy}) async {
|
||||
final Database db = await instance.database;
|
||||
final List<Map<String, dynamic>> result = await db.query(table, where: where, whereArgs: args, orderBy: orderBy);
|
||||
final List<Map<String, dynamic>> result =
|
||||
await db.query(table, where: where, whereArgs: args, orderBy: orderBy);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
@ -123,8 +129,8 @@ class DbService extends BaseService {
|
|||
// raw SQL commands. This method uses a raw query to give the row count.
|
||||
Future<int?> queryRowCount(String table) async {
|
||||
final Database db = await instance.database;
|
||||
final int? result = Sqflite.firstIntValue(
|
||||
await db.rawQuery('SELECT COUNT(*) FROM $table'));
|
||||
final int? result =
|
||||
Sqflite.firstIntValue(await db.rawQuery('SELECT COUNT(*) FROM $table'));
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
@ -133,7 +139,8 @@ class DbService extends BaseService {
|
|||
Future<int> update(String table, Map<String, dynamic> row) async {
|
||||
final Database db = await instance.database;
|
||||
final int id = row['id'] as int;
|
||||
final int result = await db.update(table, row, where: 'id = ?', whereArgs: [id]);
|
||||
final int result =
|
||||
await db.update(table, row, where: 'id = ?', whereArgs: [id]);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
@ -151,7 +158,8 @@ class DbService extends BaseService {
|
|||
return result;
|
||||
}
|
||||
|
||||
Future<int> deleteByWhere(String table, String where, List<dynamic> args) async {
|
||||
Future<int> deleteByWhere(
|
||||
String table, String where, List<dynamic> args) async {
|
||||
final Database db = await instance.database;
|
||||
final int result = await db.delete(table, where: where, whereArgs: args);
|
||||
return result;
|
||||
|
|
|
|||
|
|
@ -15,4 +15,9 @@ bool isNumeric(String? s) {
|
|||
String formatDecimal(double value) {
|
||||
if (value % 1 == 0) return value.toStringAsFixed(0).toString();
|
||||
return value.toString();
|
||||
}
|
||||
|
||||
double parseNumeric(String value) {
|
||||
|
||||
return double.tryParse(value) ?? 0;
|
||||
}
|
||||
|
|
@ -1,7 +1,10 @@
|
|||
|
||||
import 'package:satu/core/models/dictionary/category_row_data.dart';
|
||||
import 'package:satu/core/models/dictionary/good_row_data.dart';
|
||||
import 'package:satu/views/dictionaries/category/category_edit.dart';
|
||||
import 'package:satu/views/dictionaries/category/category_select_view.dart';
|
||||
import 'package:satu/views/dictionaries/category/category_view.dart';
|
||||
import 'package:satu/views/dictionaries/goods/goods_edit.dart';
|
||||
import 'package:satu/views/dictionaries/goods/goods_view.dart';
|
||||
import 'package:satu/views/work/views/add_by_barcode/add_by_barcode_view.dart';
|
||||
import 'package:satu/views/work/views/add_product/add_product_view.dart';
|
||||
|
|
@ -56,7 +59,7 @@ Route<dynamic> generateRoute(RouteSettings settings) {
|
|||
case paymentViewRoute:
|
||||
return _getPageRoute(
|
||||
routeName: settings.name!,
|
||||
viewToShow: PaymentView(),
|
||||
viewToShow: const PaymentView(),
|
||||
);
|
||||
case categoryEditRoute:
|
||||
final CategoryRowDao category = settings.arguments! as CategoryRowDao;
|
||||
|
|
@ -69,10 +72,11 @@ Route<dynamic> generateRoute(RouteSettings settings) {
|
|||
routeName: settings.name!,
|
||||
viewToShow: CategorySelectView(),
|
||||
);
|
||||
case goodsDictionaryViewRoute:
|
||||
case goodsEditRoute:
|
||||
final GoodRowDao good = settings.arguments! as GoodRowDao;
|
||||
return _getPageRoute(
|
||||
routeName: settings.name!,
|
||||
viewToShow: GoodsDictionaryView(),
|
||||
viewToShow: GoodEdit(good: good,),
|
||||
);
|
||||
|
||||
// case ImageShowRoute:
|
||||
|
|
|
|||
|
|
@ -4,8 +4,8 @@ import 'app_colors.dart';
|
|||
|
||||
// Box Decorations
|
||||
BoxDecoration fieldDecoration = const BoxDecoration(color: whiteColor);
|
||||
BoxDecoration disabledFieldDecoration = BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(5), color: Colors.grey[100]);
|
||||
BoxDecoration disabledFieldDecoration =
|
||||
const BoxDecoration(color: disableColor);
|
||||
|
||||
LinearGradient primaryGradient = const LinearGradient(
|
||||
colors: [
|
||||
|
|
@ -34,6 +34,6 @@ const TextStyle dropDownTradeTypeTextStyle =
|
|||
BoxShadow buttonShadowBox =
|
||||
const BoxShadow(blurRadius: 10, color: shadowColor, offset: Offset(0, 4));
|
||||
BoxShadow inputShadowBox =
|
||||
const BoxShadow(blurRadius: 1, color: shadowColor, offset: Offset(0, 2));
|
||||
const BoxShadow(blurRadius: 1, color: shadowColor, offset: Offset(0, 2));
|
||||
BoxShadow cardShadowBox = const BoxShadow(
|
||||
blurRadius: 3, color: Color.fromRGBO(0, 0, 0, 0.15), offset: Offset(0, 1));
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ import 'package:flutter/material.dart';
|
|||
import 'package:logger/logger.dart';
|
||||
import 'package:satu/core/entity/category_entity.dart';
|
||||
import 'package:satu/core/models/dialog_models.dart';
|
||||
import 'package:satu/core/models/dictionary/category_row_data.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';
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:satu/core/entity/category_entity.dart';
|
||||
import 'package:satu/core/entity/goods_entity.dart';
|
||||
import 'package:satu/core/models/dictionary/category_row_data.dart';
|
||||
import 'package:satu/core/redux/actions/sell_actions.dart';
|
||||
import 'package:satu/core/redux/store.dart';
|
||||
import 'package:satu/core/services/dictionary_service.dart';
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:satu/core/entity/category_entity.dart';
|
||||
import 'package:satu/core/entity/goods_entity.dart';
|
||||
import 'package:satu/core/models/dictionary/category_row_data.dart';
|
||||
import 'package:satu/core/redux/actions/sell_actions.dart';
|
||||
import 'package:satu/core/redux/store.dart';
|
||||
import 'package:satu/core/services/dictionary_service.dart';
|
||||
|
|
@ -150,11 +151,3 @@ class _CategoryDictionaryViewState extends State<CategoryDictionaryView> {
|
|||
}
|
||||
}
|
||||
|
||||
class CategoryRowDao {
|
||||
CategoryRowDao(this.name, this.parentName, this.id, {this.parentId = 0});
|
||||
|
||||
final String name;
|
||||
final String parentName;
|
||||
final int? id;
|
||||
final int? parentId;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,175 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:logger/logger.dart';
|
||||
import 'package:satu/core/entity/category_entity.dart';
|
||||
import 'package:satu/core/models/dialog_models.dart';
|
||||
import 'package:satu/core/models/dictionary/category_row_data.dart';
|
||||
import 'package:satu/core/models/dictionary/good_row_data.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/routes/route_names.dart';
|
||||
import 'package:satu/shared/ui_helpers.dart';
|
||||
import 'package:satu/views/dictionaries/category/category_view.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';
|
||||
import 'package:satu/widgets/fields/note_text.dart';
|
||||
|
||||
class GoodEdit extends StatefulWidget {
|
||||
const GoodEdit({
|
||||
required this.good,
|
||||
Key? key,
|
||||
}) : super(key: key);
|
||||
final GoodRowDao 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 _controller;
|
||||
|
||||
String parentCategoryName = '';
|
||||
int? parentCategoryId;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
if (widget.good.categoryId != null) {
|
||||
parentCategoryId = widget.good.categoryId;
|
||||
}
|
||||
_controller = TextEditingController(text: widget.good.name);
|
||||
|
||||
getAndStateCategoryName(parentCategoryId);
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_controller.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
Future<void> getAndStateCategoryName(int? id) async {
|
||||
String name = '';
|
||||
if (id == null) {
|
||||
} else if (id == 0) {
|
||||
name = 'Корневая категория';
|
||||
} else {
|
||||
log.i('message $id');
|
||||
final Category? category = await _dictionaryService.getCategoryById(id);
|
||||
if (category != null) {
|
||||
name = category.name;
|
||||
}
|
||||
log.i('message $name');
|
||||
}
|
||||
|
||||
setState(() {
|
||||
parentCategoryName = name;
|
||||
parentCategoryId = id;
|
||||
});
|
||||
}
|
||||
|
||||
@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: _controller,
|
||||
labelText: 'Номенклатурный номер',
|
||||
placeholder: 'Не присвоен',
|
||||
),
|
||||
LineTile(
|
||||
parentCategoryName,
|
||||
onTap: selectCategory,
|
||||
labelText: 'Категория',
|
||||
placeholder: 'Выберите категорию',
|
||||
),
|
||||
verticalSpaceSmall,
|
||||
InputField(
|
||||
controller: _controller,
|
||||
labelText: 'Наименование',
|
||||
placeholder: 'Введите наименование товара',
|
||||
),
|
||||
InputField(
|
||||
controller: _controller,
|
||||
labelText: 'Розничная цена',
|
||||
placeholder: 'Введите розничную цену',
|
||||
),
|
||||
InputField(
|
||||
controller: _controller,
|
||||
labelText: 'Оптовая цена',
|
||||
placeholder: 'Введите оптовую цену',
|
||||
),
|
||||
InputField(
|
||||
controller: _controller,
|
||||
labelText:
|
||||
'Закупочная цена для автоматически пополняемого товара',
|
||||
placeholder: 'Введите закупочную цену',
|
||||
),
|
||||
InputField(
|
||||
controller: _controller,
|
||||
labelText: 'EAN Штрих-код',
|
||||
placeholder: 'Введите EAN',
|
||||
),
|
||||
InputField(
|
||||
controller: _controller,
|
||||
labelText: 'Наименование',
|
||||
placeholder: 'Введите наименование товара',
|
||||
),
|
||||
Padding(
|
||||
padding:
|
||||
const EdgeInsets.symmetric(horizontal: 45.0, vertical: 20.0),
|
||||
child: BusyButton(title: 'СОХРАНИТЬ', onPressed: () {}),
|
||||
),
|
||||
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: 'Отмена');
|
||||
|
||||
return response.confirmed;
|
||||
},
|
||||
isDanger: true,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> selectCategory() async {
|
||||
final dynamic result =
|
||||
await _navigatorService.push(categorySelectViewRoute);
|
||||
if (result != null) {
|
||||
getAndStateCategoryName(result as int);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -2,6 +2,7 @@ import 'package:flutter/material.dart';
|
|||
import 'package:flutter_svg/svg.dart';
|
||||
import 'package:satu/core/entity/category_entity.dart';
|
||||
import 'package:satu/core/entity/goods_entity.dart';
|
||||
import 'package:satu/core/models/dictionary/good_row_data.dart';
|
||||
import 'package:satu/core/redux/actions/sell_actions.dart';
|
||||
import 'package:satu/core/services/dictionary_service.dart';
|
||||
import 'package:satu/core/services/navigator_service.dart';
|
||||
|
|
@ -68,7 +69,7 @@ class _GoodsDictionaryViewState extends State<GoodsDictionaryView> {
|
|||
child: Material(
|
||||
color: Colors.transparent,
|
||||
child: InkWell(
|
||||
onTap: (){},
|
||||
onTap: () {},
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(16.0),
|
||||
child: SvgPicture.asset(
|
||||
|
|
@ -99,9 +100,13 @@ class _GoodsDictionaryViewState extends State<GoodsDictionaryView> {
|
|||
itemBuilder: (BuildContext context, int index) {
|
||||
final GoodRowDao good = items[index];
|
||||
return DictionaryTile(
|
||||
onPress: () {
|
||||
locator<NavigatorService>()
|
||||
.push(goodsEditRoute, arguments: good);
|
||||
},
|
||||
child: ProductTitleWidget(
|
||||
name: good.name,
|
||||
categoryName: good.category,
|
||||
categoryName: good.categoryName,
|
||||
ean: good.ean,
|
||||
),
|
||||
);
|
||||
|
|
@ -118,7 +123,8 @@ class _GoodsDictionaryViewState extends State<GoodsDictionaryView> {
|
|||
),
|
||||
floatingActionButton: FloatingActionButton(
|
||||
elevation: 2,
|
||||
onPressed: () => locator<NavigatorService>().push(categoryEditRoute),
|
||||
onPressed: () => locator<NavigatorService>()
|
||||
.push(goodsEditRoute, arguments: GoodRowDao('', '')),
|
||||
child: const Icon(
|
||||
Icons.add_rounded,
|
||||
size: 34.0,
|
||||
|
|
@ -149,7 +155,7 @@ class _GoodsDictionaryViewState extends State<GoodsDictionaryView> {
|
|||
});
|
||||
final String parentName = category.name;
|
||||
final GoodRowDao rowDao = GoodRowDao(element.name, parentName,
|
||||
ean: element.ean, id: element.id);
|
||||
ean: element.ean, id: element.id, categoryId: element.categoryId);
|
||||
list.add(rowDao);
|
||||
});
|
||||
setState(() {
|
||||
|
|
@ -157,12 +163,3 @@ class _GoodsDictionaryViewState extends State<GoodsDictionaryView> {
|
|||
});
|
||||
}
|
||||
}
|
||||
|
||||
class GoodRowDao {
|
||||
GoodRowDao(this.name, this.category, {this.ean, this.id});
|
||||
|
||||
final String name;
|
||||
final String category;
|
||||
final String? ean;
|
||||
final int? id;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -23,25 +23,30 @@ class ContragentSelectBar extends StatelessWidget {
|
|||
locator<NavigatorService>().push(contragentSelectViewRoute);
|
||||
},
|
||||
child: Padding(
|
||||
padding: EdgeInsets.symmetric( vertical: 8.w, horizontal: 15.w ),
|
||||
padding: EdgeInsets.symmetric(vertical: 8.w, horizontal: 15.w),
|
||||
child: Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
const Text(
|
||||
'Контрагент',
|
||||
style: TextStyle(fontSize: ScreenUtil().setSp(10), color: placeholderColor),
|
||||
style:
|
||||
TextStyle(fontSize: 10, color: placeholderColor),
|
||||
),
|
||||
Text(
|
||||
value,
|
||||
style: TextStyle(fontSize: ScreenUtil().setSp(14), color: textColor),
|
||||
style:
|
||||
const TextStyle(fontSize: 14, color: textColor),
|
||||
),
|
||||
],
|
||||
)),
|
||||
Center(
|
||||
child: Icon(Icons.arrow_forward_ios, size: ScreenUtil().setSp(14),),
|
||||
const Center(
|
||||
child: Icon(
|
||||
Icons.arrow_forward_ios,
|
||||
size: 14,
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
|
|
|
|||
|
|
@ -123,7 +123,7 @@ class _ProductListItemState extends State<ProductListItem> {
|
|||
),
|
||||
),
|
||||
SizedBox(
|
||||
width: 100.w,
|
||||
width: 100,
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.end,
|
||||
children: [
|
||||
|
|
@ -131,8 +131,8 @@ class _ProductListItemState extends State<ProductListItem> {
|
|||
padding: const EdgeInsets.only(bottom: 3.0),
|
||||
child: Text(
|
||||
'${widget.price} ₸',
|
||||
style: TextStyle(
|
||||
fontSize: 14.sp,
|
||||
style: const TextStyle(
|
||||
fontSize: 14,
|
||||
fontWeight: FontWeight.w500,
|
||||
color: textColor),
|
||||
),
|
||||
|
|
@ -143,7 +143,7 @@ class _ProductListItemState extends State<ProductListItem> {
|
|||
Material(
|
||||
color: Colors.transparent,
|
||||
borderRadius:
|
||||
BorderRadius.circular(ScreenUtil().radius(5)),
|
||||
BorderRadius.circular(5),
|
||||
child: InkWell(
|
||||
onTap: () {
|
||||
Redux.store!.dispatch(counterOrEditSellItem(
|
||||
|
|
@ -156,35 +156,35 @@ class _ProductListItemState extends State<ProductListItem> {
|
|||
borderRadius: BorderRadius.circular(
|
||||
ScreenUtil().radius(5)),
|
||||
border: Border.all(
|
||||
width: 1.0.sp, color: successColor)),
|
||||
child: Icon(
|
||||
width: 1, color: successColor)),
|
||||
child: const Icon(
|
||||
Icons.add,
|
||||
color: successColor,
|
||||
size: 20.0.sp,
|
||||
size: 20,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
Container(
|
||||
width: 45.w,
|
||||
margin: EdgeInsets.symmetric(horizontal: 5.w),
|
||||
width: 45,
|
||||
margin: const EdgeInsets.symmetric(horizontal: 5.0),
|
||||
decoration: BoxDecoration(
|
||||
color: whiteColor,
|
||||
borderRadius:
|
||||
BorderRadius.circular(ScreenUtil().radius(5)),
|
||||
BorderRadius.circular(5),
|
||||
boxShadow: [cardShadowBox]),
|
||||
child: InkWell(
|
||||
onTap: () {
|
||||
editProductModal();
|
||||
},
|
||||
child: Padding(
|
||||
padding: EdgeInsets.symmetric(vertical: 6.0.w),
|
||||
padding: const EdgeInsets.symmetric(vertical: 6.0),
|
||||
child: SizedBox(
|
||||
width: 45.w,
|
||||
width: 45,
|
||||
child: Text(
|
||||
'${widget.count} шт',
|
||||
style: TextStyle(
|
||||
fontSize: 10.sp, color: placeholderColor),
|
||||
style: const TextStyle(
|
||||
fontSize: 10, color: placeholderColor),
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
),
|
||||
|
|
@ -194,7 +194,7 @@ class _ProductListItemState extends State<ProductListItem> {
|
|||
Material(
|
||||
color: Colors.transparent,
|
||||
borderRadius:
|
||||
BorderRadius.circular(ScreenUtil().radius(5)),
|
||||
BorderRadius.circular(5),
|
||||
child: InkWell(
|
||||
onTap: () {
|
||||
if (widget.count! > 1.0) {
|
||||
|
|
@ -207,7 +207,7 @@ class _ProductListItemState extends State<ProductListItem> {
|
|||
decoration: BoxDecoration(
|
||||
//color: whiteColor,
|
||||
borderRadius: BorderRadius.circular(
|
||||
ScreenUtil().radius(5)),
|
||||
5),
|
||||
border: Border.all(
|
||||
width: 1.0.sp,
|
||||
color: widget.count! <= 1.0
|
||||
|
|
@ -218,7 +218,7 @@ class _ProductListItemState extends State<ProductListItem> {
|
|||
color: widget.count! <= 1.0
|
||||
? disableColor
|
||||
: dangerColor,
|
||||
size: 20.0.sp,
|
||||
size: 20,
|
||||
),
|
||||
),
|
||||
),
|
||||
|
|
|
|||
|
|
@ -61,7 +61,8 @@ class SellView extends StatelessWidget {
|
|||
shrinkWrap: true,
|
||||
itemCount: state.items!.length,
|
||||
itemBuilder: (BuildContext context, int index) {
|
||||
final ProductDao product = state.items!.elementAt(index);
|
||||
final ProductDao product =
|
||||
state.items!.elementAt(index);
|
||||
return ProductListItem(
|
||||
key: UniqueKey(),
|
||||
ean: product.eanCode,
|
||||
|
|
@ -109,8 +110,8 @@ class SellView extends StatelessWidget {
|
|||
mini: true,
|
||||
elevation: 2,
|
||||
backgroundColor: successColor,
|
||||
onPressed: () => locator<NavigatorService>()
|
||||
.push(paymentViewRoute),
|
||||
onPressed: () =>
|
||||
locator<NavigatorService>().push(paymentViewRoute),
|
||||
child: Icon(Icons.check, color: whiteColor, size: 35.sp),
|
||||
)),
|
||||
Column(
|
||||
|
|
|
|||
|
|
@ -1,12 +1,12 @@
|
|||
import 'package:satu/core/models/flow/product_dao.dart';
|
||||
|
||||
num sumProducts(List<ProductDao> list) {
|
||||
num result = 0.0;
|
||||
double sumProducts(List<ProductDao> list) {
|
||||
double result = 0.0;
|
||||
if (list.isNotEmpty) {
|
||||
for( final ProductDao product in list) {
|
||||
final String val = (product.price! * product.count!).toStringAsFixed(5);
|
||||
// result += product.price! * product.count!;
|
||||
result += num.parse(val);
|
||||
result += double.parse(val);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
|
|
|
|||
|
|
@ -1,13 +1,24 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:satu/core/utils/utils_parse.dart';
|
||||
import 'package:satu/shared/app_colors.dart';
|
||||
import 'package:satu/shared/ui_helpers.dart';
|
||||
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
||||
|
||||
class CombineDock extends StatelessWidget {
|
||||
const CombineDock({Key? key}) : super(key: key);
|
||||
const CombineDock({
|
||||
required this.bankSum,
|
||||
required this.cashNum,
|
||||
required this.totalSum,
|
||||
Key? key,
|
||||
}) : super(key: key);
|
||||
final double bankSum;
|
||||
final double cashNum;
|
||||
final double totalSum;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final double total = bankSum + cashNum;
|
||||
final double shortChange = (total - totalSum) < 0 ? 0 : total - totalSum;
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
|
|
@ -29,16 +40,16 @@ class CombineDock extends StatelessWidget {
|
|||
padding: const EdgeInsets.all(15.0),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: const [
|
||||
Text(
|
||||
children: [
|
||||
const Text(
|
||||
'К оплате',
|
||||
style: TextStyle(
|
||||
fontSize: 14,
|
||||
),
|
||||
),
|
||||
Text(
|
||||
'1200 ₸',
|
||||
style: TextStyle(fontSize: 20),
|
||||
'${formatDecimal(total)} ₸',
|
||||
style: const TextStyle(fontSize: 20),
|
||||
),
|
||||
],
|
||||
),
|
||||
|
|
@ -54,48 +65,48 @@ class CombineDock extends StatelessWidget {
|
|||
children: [
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: const [
|
||||
Text(
|
||||
children: [
|
||||
const Text(
|
||||
'Банковская карта',
|
||||
style:
|
||||
TextStyle(fontSize: 12, color: placeholderColor),
|
||||
),
|
||||
Text(
|
||||
'1200 ₸',
|
||||
style:
|
||||
TextStyle(fontSize: 12, color: placeholderColor),
|
||||
'${formatDecimal(bankSum)} ₸',
|
||||
style: const TextStyle(
|
||||
fontSize: 12, color: placeholderColor),
|
||||
),
|
||||
],
|
||||
),
|
||||
verticalSpaceSmall,
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: const [
|
||||
Text(
|
||||
children: [
|
||||
const Text(
|
||||
'Наличными',
|
||||
style:
|
||||
TextStyle(fontSize: 12, color: placeholderColor),
|
||||
),
|
||||
Text(
|
||||
'0 ₸',
|
||||
style:
|
||||
TextStyle(fontSize: 12, color: placeholderColor),
|
||||
'${formatDecimal(cashNum)} ₸',
|
||||
style: const TextStyle(
|
||||
fontSize: 12, color: placeholderColor),
|
||||
),
|
||||
],
|
||||
),
|
||||
verticalSpaceSmall,
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: const [
|
||||
Text(
|
||||
children: [
|
||||
const Text(
|
||||
'Сдача',
|
||||
style:
|
||||
TextStyle(fontSize: 12, color: placeholderColor),
|
||||
),
|
||||
Text(
|
||||
'0 ₸',
|
||||
style:
|
||||
TextStyle(fontSize: 12, color: placeholderColor),
|
||||
'${formatDecimal(shortChange)} ₸',
|
||||
style: const TextStyle(
|
||||
fontSize: 12, color: placeholderColor),
|
||||
),
|
||||
],
|
||||
)
|
||||
|
|
|
|||
|
|
@ -16,23 +16,53 @@ import 'package:satu/widgets/fields/line_checkbox.dart';
|
|||
|
||||
class PaymentView extends StatefulWidget {
|
||||
const PaymentView();
|
||||
|
||||
@override
|
||||
_PaymentViewState createState() => _PaymentViewState();
|
||||
}
|
||||
|
||||
class _PaymentViewState extends State<PaymentView> {
|
||||
bool combine = true;
|
||||
late num _sum;
|
||||
late double _sum;
|
||||
double _bankSum = 0;
|
||||
double _cashSum = 0;
|
||||
bool isCard = false;
|
||||
|
||||
late TextEditingController _bankSumCtrl;
|
||||
late TextEditingController _cashSumCtrl;
|
||||
|
||||
final FocusNode _focusCash = FocusNode();
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_sum = sumProducts(Redux.store!.state.sellState!.items!);
|
||||
_bankSumCtrl = TextEditingController(text: formatDecimal(_sum.toDouble()));
|
||||
_cashSumCtrl = TextEditingController(text: '0');
|
||||
_bankSum = _sum;
|
||||
_cashSum = 0;
|
||||
_bankSumCtrl = TextEditingController(text: formatDecimal(_bankSum));
|
||||
_cashSumCtrl = TextEditingController(text: formatDecimal(_cashSum));
|
||||
_bankSumCtrl.addListener(() {
|
||||
if( _bankSumCtrl.text.isNotEmpty) {
|
||||
setState(() {
|
||||
_bankSum = parseNumeric(_bankSumCtrl.text);
|
||||
});
|
||||
} else {
|
||||
setState(() {
|
||||
_bankSum = 0 ;
|
||||
});
|
||||
}
|
||||
});
|
||||
_cashSumCtrl.addListener(() {
|
||||
if( _cashSumCtrl.text.isNotEmpty) {
|
||||
setState(() {
|
||||
_cashSum = parseNumeric(_cashSumCtrl.text);
|
||||
});
|
||||
} else {
|
||||
setState(() {
|
||||
_cashSum = 0 ;
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
|
|
@ -114,6 +144,7 @@ class _PaymentViewState extends State<PaymentView> {
|
|||
labelText: 'Банковская карта',
|
||||
placeholder: 'Укажите сумму',
|
||||
suffixText: '₸',
|
||||
nextFocusNode: _focusCash,
|
||||
textInputType: const TextInputType.numberWithOptions(decimal: true),
|
||||
),
|
||||
InputField(
|
||||
|
|
@ -121,25 +152,43 @@ class _PaymentViewState extends State<PaymentView> {
|
|||
labelText: 'Наличные',
|
||||
placeholder: 'Укажите сумму наличных',
|
||||
suffixText: '₸',
|
||||
fieldFocusNode: _focusCash,
|
||||
enterPressed: () {
|
||||
FocusScope.of(context).unfocus();
|
||||
},
|
||||
textInputType: const TextInputType.numberWithOptions(decimal: true),
|
||||
),
|
||||
const CombineDock()
|
||||
CombineDock(
|
||||
bankSum: _bankSum,
|
||||
cashNum: _cashSum,
|
||||
totalSum: _sum,
|
||||
)
|
||||
],
|
||||
);
|
||||
}
|
||||
return Column(
|
||||
children: const [
|
||||
children: [
|
||||
LineCheckBox(
|
||||
'Банковская карта',
|
||||
value: true,
|
||||
value: isCard == true,
|
||||
onTap: () {
|
||||
setState(() {
|
||||
isCard = true;
|
||||
});
|
||||
},
|
||||
),
|
||||
Divider(
|
||||
const Divider(
|
||||
height: 1,
|
||||
color: disableColor,
|
||||
),
|
||||
LineCheckBox(
|
||||
'Оплата наличными',
|
||||
value: false,
|
||||
value: isCard == false,
|
||||
onTap: () {
|
||||
setState(() {
|
||||
isCard = false;
|
||||
});
|
||||
},
|
||||
),
|
||||
],
|
||||
);
|
||||
|
|
|
|||
|
|
@ -122,9 +122,7 @@ class _InputFieldState extends State<InputField> {
|
|||
child: TextFormField(
|
||||
style: TextStyle(
|
||||
color: textColor,
|
||||
fontSize: widget.smallVersion
|
||||
? 12
|
||||
: 14),
|
||||
fontSize: widget.smallVersion ? 12 : 14),
|
||||
controller: widget.controller,
|
||||
keyboardType: widget.textInputType,
|
||||
focusNode: widget.fieldFocusNode,
|
||||
|
|
@ -152,7 +150,7 @@ class _InputFieldState extends State<InputField> {
|
|||
filled: true,
|
||||
suffixText: widget.suffixText,
|
||||
suffixStyle: const TextStyle(color: textColor),
|
||||
fillColor: whiteColor,
|
||||
fillColor: widget.isReadOnly ? disableColor : whiteColor,
|
||||
border: InputBorder.none,
|
||||
hintStyle: TextStyle(
|
||||
fontSize: widget.smallVersion
|
||||
|
|
|
|||
|
|
@ -44,12 +44,14 @@ class LineCheckBox extends StatelessWidget {
|
|||
),
|
||||
),
|
||||
SizedBox(
|
||||
width: 20.w,
|
||||
width: 20,
|
||||
height: 20,
|
||||
child: Visibility(
|
||||
visible: value,
|
||||
child: const Icon(
|
||||
Icons.check,
|
||||
color: primaryColor,
|
||||
size: 20,
|
||||
),
|
||||
),
|
||||
)
|
||||
|
|
|
|||
|
|
@ -5,8 +5,11 @@ import 'package:flutter_screenutil/flutter_screenutil.dart';
|
|||
import 'note_text.dart';
|
||||
|
||||
class LineTile extends StatelessWidget {
|
||||
const LineTile(this.text, { required this.onTap, this.labelText });
|
||||
const LineTile(this.text,
|
||||
{required this.onTap, this.labelText, this.placeholder = 'Выберите'});
|
||||
|
||||
final String text;
|
||||
final String placeholder;
|
||||
final String? labelText;
|
||||
final Function() onTap;
|
||||
|
||||
|
|
@ -18,13 +21,11 @@ class LineTile extends StatelessWidget {
|
|||
if (labelText != null)
|
||||
Padding(
|
||||
padding:
|
||||
const EdgeInsets.symmetric(horizontal: 14.0, vertical: 5.0),
|
||||
const EdgeInsets.symmetric(horizontal: 14.0, vertical: 5.0),
|
||||
child: NoteText(labelText ?? ''),
|
||||
),
|
||||
Container(
|
||||
decoration: const BoxDecoration(
|
||||
color: whiteColor
|
||||
),
|
||||
decoration: const BoxDecoration(color: whiteColor),
|
||||
child: Material(
|
||||
color: Colors.transparent,
|
||||
child: InkWell(
|
||||
|
|
@ -34,17 +35,25 @@ class LineTile extends StatelessWidget {
|
|||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Text(
|
||||
text,
|
||||
style: TextStyle(
|
||||
fontSize: 14,
|
||||
fontWeight: FontWeight.normal,
|
||||
color: textColor
|
||||
if (text.isNotEmpty)
|
||||
Text(
|
||||
text,
|
||||
style: const TextStyle(
|
||||
fontSize: 14,
|
||||
fontWeight: FontWeight.normal,
|
||||
color: textColor),
|
||||
),
|
||||
),
|
||||
SizedBox(
|
||||
if (text.isEmpty)
|
||||
Text(
|
||||
placeholder,
|
||||
style: const TextStyle(
|
||||
fontSize: 12,
|
||||
fontWeight: FontWeight.normal,
|
||||
color: placeholderColor),
|
||||
),
|
||||
const SizedBox(
|
||||
width: 20,
|
||||
child: const Icon(
|
||||
child: Icon(
|
||||
Icons.chevron_right,
|
||||
color: textColor,
|
||||
),
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ class ProductTitleWidget extends StatelessWidget {
|
|||
children: [
|
||||
Text(
|
||||
name,
|
||||
style: TextStyle(fontSize: 14.sp, color: textColor),
|
||||
style: const TextStyle(fontSize: 14, color: textColor),
|
||||
overflow: TextOverflow.ellipsis,
|
||||
maxLines: 2,
|
||||
),
|
||||
|
|
@ -28,12 +28,12 @@ class ProductTitleWidget extends StatelessWidget {
|
|||
if (ean != null)
|
||||
Text(
|
||||
'Штрих-код: $ean',
|
||||
style: TextStyle(color: placeholderColor, fontSize: 10.sp),
|
||||
style: const TextStyle(color: placeholderColor, fontSize: 10),
|
||||
),
|
||||
if (categoryName != null)
|
||||
Text(
|
||||
'Категория: $categoryName',
|
||||
style: TextStyle(color: placeholderColor, fontSize: 10.sp),
|
||||
style: const TextStyle(color: placeholderColor, fontSize: 10),
|
||||
)
|
||||
],
|
||||
);
|
||||
|
|
|
|||
Loading…
Reference in New Issue