product edit modal finished
parent
94823fcd56
commit
91e43dbcf4
|
|
@ -24,4 +24,7 @@ linter:
|
||||||
always_put_required_named_parameters_first: true
|
always_put_required_named_parameters_first: true
|
||||||
|
|
||||||
# Util classes are awesome!
|
# Util classes are awesome!
|
||||||
avoid_classes_with_only_static_members: true
|
avoid_classes_with_only_static_members: true
|
||||||
|
|
||||||
|
# Avoid returning an awaited expression when the expression type is assignable to the function's return type.
|
||||||
|
unnecessary_await_in_return: false
|
||||||
|
|
@ -1,3 +1,5 @@
|
||||||
|
import 'package:satu/core/utils/utils_parse.dart';
|
||||||
|
|
||||||
/// user_id : 10
|
/// user_id : 10
|
||||||
/// company_id : 281
|
/// company_id : 281
|
||||||
/// kassa_id : 3
|
/// kassa_id : 3
|
||||||
|
|
@ -19,13 +21,13 @@ class AuthResponse {
|
||||||
|
|
||||||
static AuthResponse fromMap(dynamic map) {
|
static AuthResponse fromMap(dynamic map) {
|
||||||
final AuthResponse authResponseBean = AuthResponse();
|
final AuthResponse authResponseBean = AuthResponse();
|
||||||
authResponseBean.userId = map['user_id'] as int;
|
authResponseBean.userId = cast<int>(map['user_id']);
|
||||||
authResponseBean.companyId = map['company_id'] as int;
|
authResponseBean.companyId = cast<int>(map['company_id']);
|
||||||
authResponseBean.kassaId = map['kassa_id'] as int;
|
authResponseBean.kassaId = cast<int>(map['kassa_id']);
|
||||||
authResponseBean.token = map['token']?.toString();
|
authResponseBean.token = cast<String>(map['token']);
|
||||||
authResponseBean.authAt = map['auth_at']?.toString();
|
authResponseBean.authAt = cast<String>(map['auth_at']);
|
||||||
authResponseBean.shard = map['shard'] as int;
|
authResponseBean.shard = cast<int>(map['shard']);
|
||||||
authResponseBean.message = map['message']?.toString();
|
authResponseBean.message = cast<String>(map['message']);
|
||||||
authResponseBean.operation = map['operation'] as bool;
|
authResponseBean.operation = map['operation'] as bool;
|
||||||
return authResponseBean;
|
return authResponseBean;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,30 +1,35 @@
|
||||||
import 'package:flutter/foundation.dart';
|
import 'package:flutter/foundation.dart';
|
||||||
|
|
||||||
class DialogRequest {
|
class DialogRequest {
|
||||||
final String? title;
|
|
||||||
final String? description;
|
|
||||||
final String? buttonTitle;
|
|
||||||
final String? cancelTitle;
|
|
||||||
final String? formatType;
|
|
||||||
|
|
||||||
DialogRequest(
|
DialogRequest(
|
||||||
{@required this.title,
|
{
|
||||||
@required this.description,
|
required this.title,
|
||||||
@required this.buttonTitle,
|
required this.description,
|
||||||
this.cancelTitle,
|
required this.buttonTitle,
|
||||||
this.formatType});
|
this.cancelTitle,
|
||||||
|
this.requestPrice,
|
||||||
|
this.requestCount
|
||||||
|
});
|
||||||
|
final String title;
|
||||||
|
final String description;
|
||||||
|
final String buttonTitle;
|
||||||
|
final String? cancelTitle;
|
||||||
|
|
||||||
|
final String? requestPrice;
|
||||||
|
final String? requestCount;
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class DialogResponse {
|
class DialogResponse {
|
||||||
//final String fieldOne;
|
|
||||||
//final String fieldTwo;
|
|
||||||
final String? responseText;
|
|
||||||
final bool? confirmed;
|
|
||||||
|
|
||||||
DialogResponse({
|
DialogResponse({
|
||||||
//this.fieldOne,
|
required this.confirmed,
|
||||||
//this.fieldTwo,
|
this.responsePrice,
|
||||||
this.responseText,
|
this.responseCount,
|
||||||
this.confirmed,
|
|
||||||
});
|
});
|
||||||
|
final String? responsePrice;
|
||||||
|
final String? responseCount;
|
||||||
|
final bool confirmed;
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -28,7 +28,8 @@ final Logger log = getLogger('SetSellStateAction');
|
||||||
|
|
||||||
final DbService _dbService = locator<DbService>();
|
final DbService _dbService = locator<DbService>();
|
||||||
|
|
||||||
ThunkAction<AppState> counterSellItem({required int transactionId, required num counter}) {
|
ThunkAction<AppState> counterOrEditSellItem(
|
||||||
|
{required int transactionId, required num counter, num? price}) {
|
||||||
return (Store<AppState> store) async {
|
return (Store<AppState> store) async {
|
||||||
log.i('counterSellItem');
|
log.i('counterSellItem');
|
||||||
int? appCompanyId = store.state.userState!.auth!.companyId;
|
int? appCompanyId = store.state.userState!.auth!.companyId;
|
||||||
|
|
@ -36,19 +37,33 @@ ThunkAction<AppState> counterSellItem({required int transactionId, required num
|
||||||
|
|
||||||
Transaction? transaction;
|
Transaction? transaction;
|
||||||
|
|
||||||
if (uuid != null ) {
|
if (uuid != null) {
|
||||||
List<Map<String, dynamic>> set = await _dbService.queryRowsWithWhere(
|
final List<Map<String, dynamic>> set =
|
||||||
transactionTableName,
|
await _dbService.queryRowsWithWhere(
|
||||||
'$transactionColumnAppCompanyId = ? and $transactionColumnStatus = ? and ${transactionColumnType} = ? and ${transactionColumnId} = ?',
|
transactionTableName,
|
||||||
[appCompanyId, transactionStatusPrepare, transactionTypeSell, transactionId],
|
'$transactionColumnAppCompanyId = ? '
|
||||||
orderBy: '$transactionColumnCreatedAt desc');
|
' and $transactionColumnStatus = ? '
|
||||||
|
' and $transactionColumnType = ? '
|
||||||
|
' and $transactionColumnId = ?',
|
||||||
|
[
|
||||||
|
appCompanyId,
|
||||||
|
transactionStatusPrepare,
|
||||||
|
transactionTypeSell,
|
||||||
|
transactionId
|
||||||
|
],
|
||||||
|
orderBy: '$transactionColumnCreatedAt desc');
|
||||||
if (set.isNotEmpty) {
|
if (set.isNotEmpty) {
|
||||||
transaction = Transaction.fromMap(set.first);
|
transaction = Transaction.fromMap(set.first);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (transaction != null) {
|
if (transaction != null) {
|
||||||
ProductDao item = ProductDao.fromMap(jsonDecode(transaction.data!));
|
final ProductDao item = ProductDao.fromMap(jsonDecode(transaction.data!));
|
||||||
item.count = (item.count ?? 0) + counter;
|
if (price != null) {
|
||||||
|
item.price = price;
|
||||||
|
item.count = counter;
|
||||||
|
} else {
|
||||||
|
item.count = (item.count ?? 0) + counter;
|
||||||
|
}
|
||||||
transaction.data = jsonEncode(item.toMap());
|
transaction.data = jsonEncode(item.toMap());
|
||||||
_dbService.update(transactionTableName, transaction.toMap());
|
_dbService.update(transactionTableName, transaction.toMap());
|
||||||
}
|
}
|
||||||
|
|
@ -60,21 +75,24 @@ ThunkAction<AppState> counterSellItem({required int transactionId, required num
|
||||||
ThunkAction<AppState> addSellItem({required Good good, String? excise}) {
|
ThunkAction<AppState> addSellItem({required Good good, String? excise}) {
|
||||||
return (Store<AppState> store) async {
|
return (Store<AppState> store) async {
|
||||||
log.i('addSellItem');
|
log.i('addSellItem');
|
||||||
int? appCompanyId = store.state.userState!.auth!.companyId;
|
final int? appCompanyId = store.state.userState!.auth!.companyId;
|
||||||
String? uuid = store.state.sellState!.transactionState!.uuid;
|
String? uuid = store.state.sellState!.transactionState!.uuid;
|
||||||
|
|
||||||
Transaction? transaction;
|
Transaction? transaction;
|
||||||
|
|
||||||
if (uuid != null ) {
|
if (uuid != null) {
|
||||||
List<Map<String, dynamic>> set = await _dbService.queryRowsWithWhere(
|
List<Map<String, dynamic>> set = await _dbService.queryRowsWithWhere(
|
||||||
transactionTableName,
|
transactionTableName,
|
||||||
'$transactionColumnAppCompanyId = ? and $transactionColumnStatus = ? and ${transactionColumnType} = ?',
|
'$transactionColumnAppCompanyId = ? '
|
||||||
|
' and $transactionColumnStatus = ? '
|
||||||
|
' and $transactionColumnType = ?',
|
||||||
[appCompanyId, transactionStatusPrepare, transactionTypeSell],
|
[appCompanyId, transactionStatusPrepare, transactionTypeSell],
|
||||||
orderBy: '$transactionColumnCreatedAt desc');
|
orderBy: '$transactionColumnCreatedAt desc');
|
||||||
if (set.isNotEmpty) {
|
if (set.isNotEmpty) {
|
||||||
for (Map<String, dynamic> map in set) {
|
for (Map<String, dynamic> map in set) {
|
||||||
Transaction _transaction = Transaction.fromMap(map);
|
Transaction _transaction = Transaction.fromMap(map);
|
||||||
ProductDao _product = ProductDao.fromMap(jsonDecode(_transaction.data!));
|
ProductDao _product =
|
||||||
|
ProductDao.fromMap(jsonDecode(_transaction.data!));
|
||||||
if (_product.id == good.id && _product.excise == excise) {
|
if (_product.id == good.id && _product.excise == excise) {
|
||||||
transaction = _transaction;
|
transaction = _transaction;
|
||||||
break;
|
break;
|
||||||
|
|
@ -100,8 +118,8 @@ ThunkAction<AppState> addSellItem({required Good good, String? excise}) {
|
||||||
..excise = excise;
|
..excise = excise;
|
||||||
//category add logic
|
//category add logic
|
||||||
if (good.categoryId != null) {
|
if (good.categoryId != null) {
|
||||||
List<Map<String, dynamic>> set =
|
List<Map<String, dynamic>> set = await _dbService
|
||||||
await _dbService.queryRowsWithWhere(categoryTableName, 'id = ?', [good.categoryId]);
|
.queryRowsWithWhere(categoryTableName, 'id = ?', [good.categoryId]);
|
||||||
if (set.isNotEmpty) {
|
if (set.isNotEmpty) {
|
||||||
Category category = Category.fromMap(set.first);
|
Category category = Category.fromMap(set.first);
|
||||||
item.categoryId = category.id;
|
item.categoryId = category.id;
|
||||||
|
|
@ -131,7 +149,6 @@ ThunkAction<AppState> addSellItem({required Good good, String? excise}) {
|
||||||
|
|
||||||
ThunkAction<AppState> removeSellItem({required int transactionId}) {
|
ThunkAction<AppState> removeSellItem({required int transactionId}) {
|
||||||
return (Store<AppState> store) async {
|
return (Store<AppState> store) async {
|
||||||
|
|
||||||
int? appCompanyId = store.state.userState!.auth!.companyId;
|
int? appCompanyId = store.state.userState!.auth!.companyId;
|
||||||
String? uuid = store.state.sellState!.transactionState!.uuid;
|
String? uuid = store.state.sellState!.transactionState!.uuid;
|
||||||
|
|
||||||
|
|
@ -153,7 +170,7 @@ Future<void> removeAllSellData(Store<AppState> store) async {
|
||||||
'$transactionColumnAppCompanyId = ? '
|
'$transactionColumnAppCompanyId = ? '
|
||||||
' and $transactionColumnStatus = ? '
|
' and $transactionColumnStatus = ? '
|
||||||
' and ${transactionColumnType} = ?'
|
' and ${transactionColumnType} = ?'
|
||||||
' and ${transactionColumnUuid} = ?',
|
' and ${transactionColumnUuid} = ?',
|
||||||
[appCompanyId, transactionStatusPrepare, transactionTypeSell, uuid]);
|
[appCompanyId, transactionStatusPrepare, transactionTypeSell, uuid]);
|
||||||
await loadSellData(store);
|
await loadSellData(store);
|
||||||
} catch (e, stack) {
|
} catch (e, stack) {
|
||||||
|
|
@ -179,7 +196,8 @@ Future<void> loadSellData(Store<AppState> store) async {
|
||||||
productDao.transactionId = transaction.id;
|
productDao.transactionId = transaction.id;
|
||||||
list.add(productDao);
|
list.add(productDao);
|
||||||
}
|
}
|
||||||
store.dispatch(SetSellStateAction(SellState(items: list, transactionState: TransactionState()..uuid = uuid)));
|
store.dispatch(SetSellStateAction(SellState(
|
||||||
|
items: list, transactionState: TransactionState()..uuid = uuid)));
|
||||||
} catch (e, stack) {
|
} catch (e, stack) {
|
||||||
log.e('loadSellData', e, stack);
|
log.e('loadSellData', e, stack);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,8 @@ import 'package:flutter/cupertino.dart';
|
||||||
import 'package:satu/core/models/dialog_models.dart';
|
import 'package:satu/core/models/dialog_models.dart';
|
||||||
|
|
||||||
class DialogService {
|
class DialogService {
|
||||||
final GlobalKey<NavigatorState> _dialogNavigationKey = GlobalKey<NavigatorState>();
|
final GlobalKey<NavigatorState> _dialogNavigationKey =
|
||||||
|
GlobalKey<NavigatorState>();
|
||||||
late Function(DialogRequest)? _showDialogListener;
|
late Function(DialogRequest)? _showDialogListener;
|
||||||
late Function(DialogRequest)? _showDialogInputListener;
|
late Function(DialogRequest)? _showDialogInputListener;
|
||||||
Completer<DialogResponse>? _dialogCompleter;
|
Completer<DialogResponse>? _dialogCompleter;
|
||||||
|
|
@ -22,14 +23,14 @@ class DialogService {
|
||||||
|
|
||||||
/// Calls the dialog listener and returns a Future that will wait for dialogComplete.
|
/// Calls the dialog listener and returns a Future that will wait for dialogComplete.
|
||||||
Future<DialogResponse> showDialog({
|
Future<DialogResponse> showDialog({
|
||||||
String title = 'Aman Касса',
|
String title = 'SATU',
|
||||||
String? description,
|
String? description,
|
||||||
String buttonTitle = 'Ok',
|
String buttonTitle = 'Ok',
|
||||||
}) {
|
}) {
|
||||||
_dialogCompleter = Completer<DialogResponse>();
|
_dialogCompleter = Completer<DialogResponse>();
|
||||||
_showDialogListener!(DialogRequest(
|
_showDialogListener!(DialogRequest(
|
||||||
title: title,
|
title: title,
|
||||||
description: description,
|
description: description ?? '',
|
||||||
buttonTitle: buttonTitle,
|
buttonTitle: buttonTitle,
|
||||||
));
|
));
|
||||||
return _dialogCompleter!.future;
|
return _dialogCompleter!.future;
|
||||||
|
|
@ -43,26 +44,29 @@ class DialogService {
|
||||||
String cancelTitle = 'Cancel'}) {
|
String cancelTitle = 'Cancel'}) {
|
||||||
_dialogCompleter = Completer<DialogResponse>();
|
_dialogCompleter = Completer<DialogResponse>();
|
||||||
_showDialogListener!(DialogRequest(
|
_showDialogListener!(DialogRequest(
|
||||||
title: title,
|
title: title ?? '',
|
||||||
description: description,
|
description: description ?? '',
|
||||||
buttonTitle: confirmationTitle,
|
buttonTitle: confirmationTitle,
|
||||||
cancelTitle: cancelTitle));
|
cancelTitle: cancelTitle));
|
||||||
return _dialogCompleter!.future;
|
return _dialogCompleter!.future;
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<DialogResponse> showConfirmationDialogInput(
|
Future<DialogResponse> showConfirmationDialogInput({
|
||||||
{String title = ' Aman Касса',
|
required String title,
|
||||||
String? description,
|
required String requestPrice,
|
||||||
String confirmationTitle = 'Ok',
|
required String requestCount,
|
||||||
String cancelTitle = 'Cancel',
|
String? description,
|
||||||
String? formatType}) {
|
String confirmationTitle = 'ПОДТВЕРДИТЬ',
|
||||||
|
String cancelTitle = 'Отмена',
|
||||||
|
}) {
|
||||||
_dialogCompleter = Completer<DialogResponse>();
|
_dialogCompleter = Completer<DialogResponse>();
|
||||||
_showDialogInputListener!(DialogRequest(
|
_showDialogInputListener!(DialogRequest(
|
||||||
title: title,
|
title: title,
|
||||||
description: description,
|
description: description ?? '',
|
||||||
buttonTitle: confirmationTitle,
|
buttonTitle: confirmationTitle,
|
||||||
cancelTitle: cancelTitle,
|
cancelTitle: cancelTitle,
|
||||||
formatType: formatType));
|
requestPrice: requestPrice,
|
||||||
|
requestCount: requestCount));
|
||||||
return _dialogCompleter!.future;
|
return _dialogCompleter!.future;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -3,4 +3,16 @@ List<String>? parseListString(Iterable<dynamic>? json){
|
||||||
return List<String>.from(json);
|
return List<String>.from(json);
|
||||||
}
|
}
|
||||||
|
|
||||||
T? cast<T>(x) => x is T ? x : null;
|
T? cast<T>(x) => x is T ? x : null;
|
||||||
|
|
||||||
|
bool isNumeric(String? s) {
|
||||||
|
if (s == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return double.tryParse(s) != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
String formatDecimal(double value) {
|
||||||
|
if (value % 1 == 0) return value.toStringAsFixed(0).toString();
|
||||||
|
return value.toString();
|
||||||
|
}
|
||||||
|
|
@ -3,38 +3,37 @@ import 'package:flutter/material.dart';
|
||||||
import 'app_colors.dart';
|
import 'app_colors.dart';
|
||||||
|
|
||||||
// Box Decorations
|
// Box Decorations
|
||||||
BoxDecoration fieldDecoration = BoxDecoration(color: whiteColor);
|
BoxDecoration fieldDecoration = const BoxDecoration(color: whiteColor);
|
||||||
BoxDecoration disabledFieldDecoration = BoxDecoration(
|
BoxDecoration disabledFieldDecoration = BoxDecoration(
|
||||||
borderRadius: BorderRadius.circular(5), color: Colors.grey[100]);
|
borderRadius: BorderRadius.circular(5), color: Colors.grey[100]);
|
||||||
|
|
||||||
const LinearGradient primaryGradient = LinearGradient(
|
LinearGradient primaryGradient = const LinearGradient(
|
||||||
colors: [
|
colors: [
|
||||||
primaryGrStartColor,
|
primaryGrStartColor,
|
||||||
primaryGrEndColor,
|
primaryGrEndColor,
|
||||||
],
|
],
|
||||||
begin: const FractionalOffset(0.0, 0.0),
|
begin: FractionalOffset(0.0, 0.0),
|
||||||
end: const FractionalOffset(1.0, 0.0),
|
end: FractionalOffset(1.0, 0.0),
|
||||||
stops: [0.0, 1.0],
|
stops: [0.0, 1.0]);
|
||||||
tileMode: TileMode.clamp);
|
|
||||||
|
|
||||||
// Field Variables
|
// Field Variables
|
||||||
const double fieldHeight = 55;
|
const double fieldHeight = 55;
|
||||||
const double smallFieldHeight = 40;
|
const double smallFieldHeight = 40;
|
||||||
const double inputFieldBottomMargin = 30;
|
const double inputFieldBottomMargin = 30;
|
||||||
const double inputFieldSmallBottomMargin = 0;
|
const double inputFieldSmallBottomMargin = 0;
|
||||||
const EdgeInsets fieldPadding = const EdgeInsets.symmetric(horizontal: 8.0);
|
EdgeInsets fieldPadding = const EdgeInsets.symmetric(horizontal: 8.0);
|
||||||
const EdgeInsets largeFieldPadding =
|
EdgeInsets largeFieldPadding =
|
||||||
const EdgeInsets.symmetric(horizontal: 15, vertical: 15);
|
const EdgeInsets.symmetric(horizontal: 15, vertical: 15);
|
||||||
|
|
||||||
// Text Variables
|
// Text Variables
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const TextStyle dropDownTradeTypeTextStyle =
|
const TextStyle dropDownTradeTypeTextStyle =
|
||||||
TextStyle(color: Colors.black54, fontWeight: FontWeight.bold, fontSize: 24);
|
TextStyle(color: Colors.black54, fontWeight: FontWeight.bold, fontSize: 24);
|
||||||
|
|
||||||
// Box Shadow
|
// Box Shadow
|
||||||
const BoxShadow buttonShadowBox =
|
BoxShadow buttonShadowBox =
|
||||||
BoxShadow(blurRadius: 10, color: shadowColor, offset: Offset(0, 4));
|
const BoxShadow(blurRadius: 10, color: shadowColor, offset: Offset(0, 4));
|
||||||
const BoxShadow cardShadowBox =
|
BoxShadow inputShadowBox =
|
||||||
BoxShadow(blurRadius: 3, color: Color.fromRGBO(0, 0, 0, 0.15), offset: Offset(0, 1));
|
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));
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,15 @@
|
||||||
|
import 'dart:ffi';
|
||||||
|
|
||||||
import 'package:flutter/cupertino.dart';
|
import 'package:flutter/cupertino.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
||||||
|
import 'package:satu/core/models/dialog_models.dart';
|
||||||
import 'package:satu/core/redux/actions/sell_actions.dart';
|
import 'package:satu/core/redux/actions/sell_actions.dart';
|
||||||
import 'package:satu/core/redux/store.dart';
|
import 'package:satu/core/redux/store.dart';
|
||||||
import 'package:satu/core/services/dialog_service.dart';
|
import 'package:satu/core/services/dialog_service.dart';
|
||||||
import 'package:satu/core/services/navigator_service.dart';
|
import 'package:satu/core/services/navigator_service.dart';
|
||||||
import 'package:satu/core/utils/locator.dart';
|
import 'package:satu/core/utils/locator.dart';
|
||||||
|
import 'package:satu/core/utils/utils_parse.dart';
|
||||||
import 'package:satu/routes/route_names.dart';
|
import 'package:satu/routes/route_names.dart';
|
||||||
import 'package:satu/shared/app_colors.dart';
|
import 'package:satu/shared/app_colors.dart';
|
||||||
import 'package:satu/shared/shared_styles.dart';
|
import 'package:satu/shared/shared_styles.dart';
|
||||||
|
|
@ -16,6 +20,17 @@ import 'package:satu/widgets/ui/product_title_widget.dart';
|
||||||
import 'dialog_edit_product.dart';
|
import 'dialog_edit_product.dart';
|
||||||
|
|
||||||
class ProductListItem extends StatefulWidget {
|
class ProductListItem extends StatefulWidget {
|
||||||
|
const ProductListItem(
|
||||||
|
{Key? key,
|
||||||
|
this.name = '',
|
||||||
|
this.ean,
|
||||||
|
this.categoryName,
|
||||||
|
this.price,
|
||||||
|
this.count,
|
||||||
|
this.isOdd,
|
||||||
|
this.transactionId})
|
||||||
|
: super(key: key);
|
||||||
|
|
||||||
final String name;
|
final String name;
|
||||||
final String? ean;
|
final String? ean;
|
||||||
final String? categoryName;
|
final String? categoryName;
|
||||||
|
|
@ -24,10 +39,6 @@ class ProductListItem extends StatefulWidget {
|
||||||
final bool? isOdd;
|
final bool? isOdd;
|
||||||
final int? transactionId;
|
final int? transactionId;
|
||||||
|
|
||||||
const ProductListItem(
|
|
||||||
{Key? key, this.name = '', this.ean, this.categoryName, this.price, this.count, this.isOdd, this.transactionId})
|
|
||||||
: super(key: key);
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
_ProductListItemState createState() => _ProductListItemState();
|
_ProductListItemState createState() => _ProductListItemState();
|
||||||
}
|
}
|
||||||
|
|
@ -38,7 +49,7 @@ class _ProductListItemState extends State<ProductListItem> {
|
||||||
|
|
||||||
void _onItemTapped(BuildContext context) {
|
void _onItemTapped(BuildContext context) {
|
||||||
Navigator.of(context).push(MaterialPageRoute(
|
Navigator.of(context).push(MaterialPageRoute(
|
||||||
builder: (BuildContext context) => AddByBarcodeView()));
|
builder: (BuildContext context) => const AddByBarcodeView()));
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
|
@ -61,13 +72,17 @@ class _ProductListItemState extends State<ProductListItem> {
|
||||||
context: context,
|
context: context,
|
||||||
builder: (BuildContext context) {
|
builder: (BuildContext context) {
|
||||||
return AlertDialog(
|
return AlertDialog(
|
||||||
title: const Text("Внимание"),
|
title: const Text('Внимание'),
|
||||||
content: Text("Удалить товар \"${this.widget.name}\" - ${widget.count} ед. ?"),
|
content: Text('Удалить товар '
|
||||||
|
'"${widget.name}"'
|
||||||
|
' - ${widget.count} ед. ?'),
|
||||||
actions: <Widget>[
|
actions: <Widget>[
|
||||||
TextButton(onPressed: () => Navigator.of(context).pop(true), child: const Text("Удалить")),
|
TextButton(
|
||||||
|
onPressed: () => Navigator.of(context).pop(true),
|
||||||
|
child: const Text('Удалить')),
|
||||||
TextButton(
|
TextButton(
|
||||||
onPressed: () => Navigator.of(context).pop(false),
|
onPressed: () => Navigator.of(context).pop(false),
|
||||||
child: const Text("Отмена"),
|
child: const Text('Отмена'),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
|
|
@ -75,19 +90,25 @@ class _ProductListItemState extends State<ProductListItem> {
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
onDismissed: (direction) {
|
onDismissed: (direction) {
|
||||||
Redux.store!.dispatch(removeSellItem(transactionId: this.widget.transactionId!));
|
Redux.store!
|
||||||
|
.dispatch(removeSellItem(transactionId: widget.transactionId!));
|
||||||
},
|
},
|
||||||
key: Key(widget.name ),
|
key: Key(widget.name),
|
||||||
child: ListTile(
|
child: ListTile(
|
||||||
//onTap: () => _onItemTapped(context),
|
//onTap: () => _onItemTapped(context),
|
||||||
onTap: () {},
|
onTap: () {},
|
||||||
contentPadding: const EdgeInsets.symmetric(horizontal: 10.0, vertical: 4.0),
|
contentPadding:
|
||||||
|
const EdgeInsets.symmetric(horizontal: 10.0, vertical: 4.0),
|
||||||
title: Row(
|
title: Row(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
children: [
|
children: [
|
||||||
Expanded(
|
Expanded(
|
||||||
child: ProductTitleWidget(name: widget.name, ean: widget.ean, categoryName: widget.categoryName, ),
|
child: ProductTitleWidget(
|
||||||
|
name: widget.name,
|
||||||
|
ean: widget.ean,
|
||||||
|
categoryName: widget.categoryName,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
SizedBox(
|
SizedBox(
|
||||||
width: 100.w,
|
width: 100.w,
|
||||||
|
|
@ -98,7 +119,10 @@ class _ProductListItemState extends State<ProductListItem> {
|
||||||
padding: const EdgeInsets.only(bottom: 3.0),
|
padding: const EdgeInsets.only(bottom: 3.0),
|
||||||
child: Text(
|
child: Text(
|
||||||
'${widget.price} ₸',
|
'${widget.price} ₸',
|
||||||
style: TextStyle(fontSize: 12.sp, fontWeight: FontWeight.w500, color: textColor),
|
style: TextStyle(
|
||||||
|
fontSize: 14.sp,
|
||||||
|
fontWeight: FontWeight.w500,
|
||||||
|
color: textColor),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
Row(
|
Row(
|
||||||
|
|
@ -106,17 +130,21 @@ class _ProductListItemState extends State<ProductListItem> {
|
||||||
children: [
|
children: [
|
||||||
Material(
|
Material(
|
||||||
color: Colors.transparent,
|
color: Colors.transparent,
|
||||||
borderRadius: BorderRadius.circular(ScreenUtil().radius(5)),
|
borderRadius:
|
||||||
|
BorderRadius.circular(ScreenUtil().radius(5)),
|
||||||
child: InkWell(
|
child: InkWell(
|
||||||
onTap: () {
|
onTap: () {
|
||||||
Redux.store!
|
Redux.store!.dispatch(counterOrEditSellItem(
|
||||||
.dispatch(counterSellItem(transactionId: widget.transactionId!, counter: 1.0));
|
transactionId: widget.transactionId!,
|
||||||
|
counter: 1.0));
|
||||||
},
|
},
|
||||||
child: Container(
|
child: Container(
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
//color: whiteColor,
|
//color: whiteColor,
|
||||||
borderRadius: BorderRadius.circular(ScreenUtil().radius(5)),
|
borderRadius: BorderRadius.circular(
|
||||||
border: Border.all(width: 1.0.sp, color: successColor)),
|
ScreenUtil().radius(5)),
|
||||||
|
border: Border.all(
|
||||||
|
width: 1.0.sp, color: successColor)),
|
||||||
child: Icon(
|
child: Icon(
|
||||||
Icons.add,
|
Icons.add,
|
||||||
color: successColor,
|
color: successColor,
|
||||||
|
|
@ -130,11 +158,12 @@ class _ProductListItemState extends State<ProductListItem> {
|
||||||
margin: EdgeInsets.symmetric(horizontal: 5.w),
|
margin: EdgeInsets.symmetric(horizontal: 5.w),
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
color: whiteColor,
|
color: whiteColor,
|
||||||
borderRadius: BorderRadius.circular(ScreenUtil().radius(5)),
|
borderRadius:
|
||||||
|
BorderRadius.circular(ScreenUtil().radius(5)),
|
||||||
boxShadow: [cardShadowBox]),
|
boxShadow: [cardShadowBox]),
|
||||||
child: InkWell(
|
child: InkWell(
|
||||||
onTap: (){
|
onTap: () {
|
||||||
_dialogService.showConfirmationDialogInput(description: 'asd');
|
editProductModal();
|
||||||
},
|
},
|
||||||
child: Padding(
|
child: Padding(
|
||||||
padding: EdgeInsets.symmetric(vertical: 6.0.w),
|
padding: EdgeInsets.symmetric(vertical: 6.0.w),
|
||||||
|
|
@ -142,7 +171,8 @@ class _ProductListItemState extends State<ProductListItem> {
|
||||||
width: 45.w,
|
width: 45.w,
|
||||||
child: Text(
|
child: Text(
|
||||||
'${widget.count} шт',
|
'${widget.count} шт',
|
||||||
style: TextStyle(fontSize: 8.sp, color: placeholderColor),
|
style: TextStyle(
|
||||||
|
fontSize: 10.sp, color: placeholderColor),
|
||||||
textAlign: TextAlign.center,
|
textAlign: TextAlign.center,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|
@ -151,23 +181,31 @@ class _ProductListItemState extends State<ProductListItem> {
|
||||||
),
|
),
|
||||||
Material(
|
Material(
|
||||||
color: Colors.transparent,
|
color: Colors.transparent,
|
||||||
borderRadius: BorderRadius.circular(ScreenUtil().radius(5)),
|
borderRadius:
|
||||||
|
BorderRadius.circular(ScreenUtil().radius(5)),
|
||||||
child: InkWell(
|
child: InkWell(
|
||||||
onTap: () {
|
onTap: () {
|
||||||
if (widget.count! > 1.0) {
|
if (widget.count! > 1.0) {
|
||||||
Redux.store!
|
Redux.store!.dispatch(counterOrEditSellItem(
|
||||||
.dispatch(counterSellItem(transactionId: this.widget.transactionId!, counter: -1.0));
|
transactionId: widget.transactionId!,
|
||||||
|
counter: -1.0));
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
child: Container(
|
child: Container(
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
//color: whiteColor,
|
//color: whiteColor,
|
||||||
borderRadius: BorderRadius.circular(ScreenUtil().radius(5)),
|
borderRadius: BorderRadius.circular(
|
||||||
|
ScreenUtil().radius(5)),
|
||||||
border: Border.all(
|
border: Border.all(
|
||||||
width: 1.0.sp, color: widget.count! <= 1.0 ? disableColor : dangerColor)),
|
width: 1.0.sp,
|
||||||
|
color: widget.count! <= 1.0
|
||||||
|
? disableColor
|
||||||
|
: dangerColor)),
|
||||||
child: Icon(
|
child: Icon(
|
||||||
Icons.remove,
|
Icons.remove,
|
||||||
color: widget.count! <= 1.0 ? disableColor : dangerColor,
|
color: widget.count! <= 1.0
|
||||||
|
? disableColor
|
||||||
|
: dangerColor,
|
||||||
size: 20.0.sp,
|
size: 20.0.sp,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|
@ -184,6 +222,24 @@ class _ProductListItemState extends State<ProductListItem> {
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<void> editProductModal() async {
|
||||||
|
final DialogResponse response =
|
||||||
|
await _dialogService.showConfirmationDialogInput(
|
||||||
|
title: widget.name,
|
||||||
|
requestCount: formatDecimal(widget.count!.toDouble()),
|
||||||
|
requestPrice: formatDecimal(widget.price!.toDouble()));
|
||||||
|
if (response.confirmed) {
|
||||||
|
if (isNumeric(response.responsePrice) &&
|
||||||
|
isNumeric(response.responseCount)) {
|
||||||
|
Redux.store!.dispatch(counterOrEditSellItem(
|
||||||
|
transactionId: widget.transactionId!,
|
||||||
|
counter: num.parse(response.responseCount!),
|
||||||
|
price: num.parse(response.responsePrice!),
|
||||||
|
));
|
||||||
|
} else {
|
||||||
|
_dialogService.showDialog(description: 'Не верный формат');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -37,20 +37,20 @@ class _BusyButtonState extends State<BusyButton> {
|
||||||
type: MaterialType.transparency,
|
type: MaterialType.transparency,
|
||||||
child: InkWell(
|
child: InkWell(
|
||||||
onTap: () {
|
onTap: () {
|
||||||
if(!(widget.busy || !widget.enabled))
|
if (!(widget.busy || !widget.enabled)) widget.onPressed();
|
||||||
widget.onPressed();
|
|
||||||
},
|
},
|
||||||
child: AnimatedContainer(
|
child: AnimatedContainer(
|
||||||
height: 40.h,
|
height: 40.h,
|
||||||
duration: const Duration(milliseconds: 300),
|
duration: const Duration(milliseconds: 300),
|
||||||
alignment: Alignment.center,
|
alignment: Alignment.center,
|
||||||
//margin: const EdgeInsets.symmetric(horizontal: 10.0, vertical: 10.0 ),
|
|
||||||
child: !widget.busy
|
child: !widget.busy
|
||||||
? Text(
|
? Text(
|
||||||
widget.title,
|
widget.title,
|
||||||
textAlign: TextAlign.center,
|
textAlign: TextAlign.center,
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
fontWeight: FontWeight.w400, color: blackColor, fontSize: 12.sp ),
|
fontWeight: FontWeight.w400,
|
||||||
|
color: blackColor,
|
||||||
|
fontSize: 14.sp),
|
||||||
//minFontSize: 2,
|
//minFontSize: 2,
|
||||||
maxLines: 1,
|
maxLines: 1,
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,16 @@
|
||||||
|
import 'package:flutter/cupertino.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter/services.dart';
|
import 'package:flutter/services.dart';
|
||||||
|
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
||||||
import 'package:mask_text_input_formatter/mask_text_input_formatter.dart';
|
import 'package:mask_text_input_formatter/mask_text_input_formatter.dart';
|
||||||
import 'package:satu/core/models/dialog_models.dart';
|
import 'package:satu/core/models/dialog_models.dart';
|
||||||
import 'package:satu/core/services/dialog_service.dart';
|
import 'package:satu/core/services/dialog_service.dart';
|
||||||
import 'package:satu/core/utils/locator.dart';
|
import 'package:satu/core/utils/locator.dart';
|
||||||
|
import 'package:satu/shared/app_colors.dart';
|
||||||
|
import 'package:satu/shared/ui_helpers.dart';
|
||||||
|
import 'package:satu/widgets/buttons/busy_button.dart';
|
||||||
|
import 'package:satu/widgets/fields/input_field.dart';
|
||||||
|
import 'package:satu/widgets/fields/input_field_rounded.dart';
|
||||||
|
|
||||||
class DialogManager extends StatefulWidget {
|
class DialogManager extends StatefulWidget {
|
||||||
final Widget child;
|
final Widget child;
|
||||||
|
|
@ -15,18 +22,21 @@ class DialogManager extends StatefulWidget {
|
||||||
|
|
||||||
class _DialogManagerState extends State<DialogManager> {
|
class _DialogManagerState extends State<DialogManager> {
|
||||||
final DialogService _dialogService = locator<DialogService>();
|
final DialogService _dialogService = locator<DialogService>();
|
||||||
late TextEditingController _controller;
|
late TextEditingController _controllerPrice;
|
||||||
|
late TextEditingController _controllerCount;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
_controller = new TextEditingController();
|
_controllerPrice = TextEditingController();
|
||||||
|
_controllerCount = TextEditingController();
|
||||||
_dialogService.registerDialogListener(_showDialog, _showDialogInput);
|
_dialogService.registerDialogListener(_showDialog, _showDialogInput);
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void dispose() {
|
void dispose() {
|
||||||
_controller.dispose();
|
_controllerPrice.dispose();
|
||||||
|
_controllerCount.dispose();
|
||||||
super.dispose();
|
super.dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -36,7 +46,6 @@ class _DialogManagerState extends State<DialogManager> {
|
||||||
}
|
}
|
||||||
|
|
||||||
void _showDialog(DialogRequest request) {
|
void _showDialog(DialogRequest request) {
|
||||||
|
|
||||||
var isConfirmationDialog = request.cancelTitle != null;
|
var isConfirmationDialog = request.cancelTitle != null;
|
||||||
showDialog<String>(
|
showDialog<String>(
|
||||||
context: context,
|
context: context,
|
||||||
|
|
@ -49,13 +58,13 @@ class _DialogManagerState extends State<DialogManager> {
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: <Widget>[
|
children: <Widget>[
|
||||||
Text(
|
Text(
|
||||||
request.title!,
|
request.title,
|
||||||
style: const TextStyle(fontWeight: FontWeight.bold),
|
style: const TextStyle(fontWeight: FontWeight.bold),
|
||||||
),
|
),
|
||||||
//Divider(),
|
//Divider(),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
content: Text(request.description!),
|
content: Text(request.description),
|
||||||
actions: <Widget>[
|
actions: <Widget>[
|
||||||
if (isConfirmationDialog)
|
if (isConfirmationDialog)
|
||||||
TextButton(
|
TextButton(
|
||||||
|
|
@ -70,95 +79,95 @@ class _DialogManagerState extends State<DialogManager> {
|
||||||
_dialogService
|
_dialogService
|
||||||
.dialogComplete(DialogResponse(confirmed: true));
|
.dialogComplete(DialogResponse(confirmed: true));
|
||||||
},
|
},
|
||||||
child: Text(request.buttonTitle!),
|
child: Text(request.buttonTitle),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
void _showDialogInput(DialogRequest request) {
|
void _showDialogInput(DialogRequest request) {
|
||||||
var isConfirmationDialog = request.cancelTitle != null;
|
final bool isConfirmationDialog = request.cancelTitle != null;
|
||||||
|
|
||||||
_controller.clear();
|
_controllerPrice.text = request.requestPrice ?? '';
|
||||||
|
_controllerCount.text = request.requestCount ?? '';
|
||||||
|
|
||||||
var maskFormatter = new MaskTextInputFormatter(
|
final dialogController = showDialog(
|
||||||
mask: '+% (###) ###-##-##',
|
|
||||||
filter: {"#": RegExp(r'[0-9]'), "%": RegExp(r'[7]')});
|
|
||||||
|
|
||||||
var dialogController = showDialog(
|
|
||||||
context: context,
|
context: context,
|
||||||
builder: (context) => AlertDialog(
|
builder: (context) => AlertDialog(
|
||||||
|
backgroundColor: backgroundColor,
|
||||||
shape: RoundedRectangleBorder(
|
shape: RoundedRectangleBorder(
|
||||||
borderRadius: BorderRadius.circular(5.0),
|
borderRadius: BorderRadius.circular(5.0),
|
||||||
),
|
),
|
||||||
actionsPadding: const EdgeInsets.only(right: 15, bottom: 5),
|
actionsPadding: const EdgeInsets.only(right: 15, bottom: 5),
|
||||||
title: Column(
|
content: SizedBox(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
width: ScreenUtil().setWidth(ScreenUtil().screenWidth * 0.9),
|
||||||
children: <Widget>[
|
child: Column(
|
||||||
Text(
|
mainAxisSize: MainAxisSize.min,
|
||||||
request.title!,
|
children: <Widget>[
|
||||||
style: TextStyle(fontWeight: FontWeight.bold),
|
Text(
|
||||||
),
|
request.title,
|
||||||
//Divider(),
|
style: TextStyle(
|
||||||
],
|
fontWeight: FontWeight.w400,
|
||||||
),
|
fontSize: ScreenUtil().setSp(14)),
|
||||||
content: Column(
|
maxLines: 2,
|
||||||
mainAxisSize: MainAxisSize.min,
|
overflow: TextOverflow.ellipsis,
|
||||||
children: <Widget>[
|
|
||||||
//Text(request.description),
|
|
||||||
TextField(
|
|
||||||
autofocus: true,
|
|
||||||
decoration: InputDecoration(
|
|
||||||
labelText: request.description,
|
|
||||||
hintText: request.formatType == "phone"
|
|
||||||
? "+7 (123) 456-78-90"
|
|
||||||
: ""),
|
|
||||||
controller: _controller,
|
|
||||||
onSubmitted: (value) {
|
|
||||||
_dialogService
|
|
||||||
.dialogComplete(DialogResponse(confirmed: false));
|
|
||||||
},
|
|
||||||
keyboardType: TextInputType.phone,
|
|
||||||
inputFormatters: <TextInputFormatter>[
|
|
||||||
if (request.formatType == "phone") maskFormatter,
|
|
||||||
if (request.formatType == null)
|
|
||||||
FilteringTextInputFormatter.allow(RegExp("^[0-9.]*")),
|
|
||||||
],
|
|
||||||
)
|
|
||||||
],
|
|
||||||
),
|
|
||||||
actions: <Widget>[
|
|
||||||
if (isConfirmationDialog)
|
|
||||||
RaisedButton(
|
|
||||||
//color: redColor,
|
|
||||||
child: Text(
|
|
||||||
request.cancelTitle!,
|
|
||||||
style: TextStyle(fontSize: 18),
|
|
||||||
),
|
),
|
||||||
onPressed: () {
|
verticalSpaceSmall,
|
||||||
_dialogService
|
const Divider(),
|
||||||
.dialogComplete(DialogResponse(confirmed: false));
|
verticalSpaceSmall,
|
||||||
},
|
InputFieldRounded(
|
||||||
),
|
controller: _controllerPrice,
|
||||||
SizedBox(
|
placeholder: '',
|
||||||
width: 5,
|
suffixText: '₸',
|
||||||
|
labelText: 'Стоимость товара',
|
||||||
|
textInputType:
|
||||||
|
const TextInputType.numberWithOptions(decimal: true),
|
||||||
|
),
|
||||||
|
InputFieldRounded(
|
||||||
|
textInputType:
|
||||||
|
const TextInputType.numberWithOptions(decimal: true),
|
||||||
|
controller: _controllerCount,
|
||||||
|
placeholder: '',
|
||||||
|
suffixText: 'шт',
|
||||||
|
labelText: 'Количество товара',
|
||||||
|
),
|
||||||
|
verticalSpaceSmall,
|
||||||
|
Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
|
children: [
|
||||||
|
if (isConfirmationDialog)
|
||||||
|
Expanded(
|
||||||
|
child: TextButton(
|
||||||
|
onPressed: () {
|
||||||
|
_dialogService.dialogComplete(
|
||||||
|
DialogResponse(confirmed: false));
|
||||||
|
},
|
||||||
|
//color: redColor,
|
||||||
|
child: Text(
|
||||||
|
request.cancelTitle!,
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: 14.sp, color: placeholderColor),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Expanded(
|
||||||
|
child: BusyButton(
|
||||||
|
title: request.buttonTitle,
|
||||||
|
onPressed: () {
|
||||||
|
final String _price = _controllerPrice.text;
|
||||||
|
final String _count = _controllerCount.text;
|
||||||
|
_dialogService.dialogComplete(DialogResponse(
|
||||||
|
confirmed: true,
|
||||||
|
responsePrice: _price.replaceAll(',', '.'),
|
||||||
|
responseCount: _count.replaceAll(',', '.')));
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
],
|
||||||
),
|
),
|
||||||
RaisedButton(
|
),
|
||||||
//color: primaryColor,
|
|
||||||
child: Text(
|
|
||||||
request.buttonTitle!,
|
|
||||||
style: TextStyle(fontSize: 18),
|
|
||||||
),
|
|
||||||
onPressed: () {
|
|
||||||
String _result = _controller.text;
|
|
||||||
if (request.formatType == "phone") {
|
|
||||||
_result = maskFormatter.getUnmaskedText();
|
|
||||||
}
|
|
||||||
_dialogService.dialogComplete(
|
|
||||||
DialogResponse(confirmed: true, responseText: _result));
|
|
||||||
},
|
|
||||||
),
|
|
||||||
],
|
|
||||||
));
|
));
|
||||||
dialogController.whenComplete(() {
|
dialogController.whenComplete(() {
|
||||||
//hook when press overlay and response not completed
|
//hook when press overlay and response not completed
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,195 @@
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter/services.dart';
|
||||||
|
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
||||||
|
import 'package:satu/shared/app_colors.dart';
|
||||||
|
import 'package:satu/shared/shared_styles.dart';
|
||||||
|
import 'package:satu/shared/ui_helpers.dart';
|
||||||
|
|
||||||
|
import 'note_text.dart';
|
||||||
|
|
||||||
|
class InputFieldRounded extends StatefulWidget {
|
||||||
|
final TextEditingController controller;
|
||||||
|
final TextInputType textInputType;
|
||||||
|
final bool password;
|
||||||
|
final bool search;
|
||||||
|
final bool isReadOnly;
|
||||||
|
final String placeholder;
|
||||||
|
final String? validationMessage;
|
||||||
|
final Function? enterPressed;
|
||||||
|
final bool smallVersion;
|
||||||
|
final FocusNode? fieldFocusNode;
|
||||||
|
final FocusNode? nextFocusNode;
|
||||||
|
final TextInputAction textInputAction;
|
||||||
|
final bool multiline;
|
||||||
|
final String? additionalNote;
|
||||||
|
final Function(String)? onChanged;
|
||||||
|
final TextInputFormatter? formatter;
|
||||||
|
final String? initialValue;
|
||||||
|
final String? labelText;
|
||||||
|
final String? suffixText;
|
||||||
|
|
||||||
|
InputFieldRounded(
|
||||||
|
{required this.controller,
|
||||||
|
required this.placeholder,
|
||||||
|
this.enterPressed,
|
||||||
|
this.fieldFocusNode,
|
||||||
|
this.nextFocusNode,
|
||||||
|
this.additionalNote,
|
||||||
|
this.onChanged,
|
||||||
|
this.formatter,
|
||||||
|
this.suffixText,
|
||||||
|
this.initialValue,
|
||||||
|
this.validationMessage,
|
||||||
|
this.textInputAction = TextInputAction.next,
|
||||||
|
this.textInputType = TextInputType.text,
|
||||||
|
this.password = false,
|
||||||
|
this.search = false,
|
||||||
|
this.isReadOnly = false,
|
||||||
|
this.multiline = false,
|
||||||
|
this.smallVersion = false,
|
||||||
|
this.labelText});
|
||||||
|
|
||||||
|
@override
|
||||||
|
_InputFieldRoundedState createState() => _InputFieldRoundedState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _InputFieldRoundedState extends State<InputFieldRounded> {
|
||||||
|
late bool isPassword;
|
||||||
|
late bool isSearch;
|
||||||
|
double fieldHeight = 40;
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
super.initState();
|
||||||
|
isPassword = widget.password;
|
||||||
|
isSearch = widget.search;
|
||||||
|
if (widget.search == true) {
|
||||||
|
widget.fieldFocusNode!.addListener(() {
|
||||||
|
if (widget.fieldFocusNode!.hasFocus) {
|
||||||
|
setState(() {
|
||||||
|
isSearch = !isSearch;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: <Widget>[
|
||||||
|
if (widget.labelText != null)
|
||||||
|
NoteText(
|
||||||
|
widget.labelText ?? '',
|
||||||
|
fontSize: ScreenUtil().setSp(14),
|
||||||
|
),
|
||||||
|
if (widget.labelText != null) verticalSpace(5),
|
||||||
|
Container(
|
||||||
|
constraints: BoxConstraints(
|
||||||
|
minHeight: widget.smallVersion ? 40.h : fieldHeight),
|
||||||
|
alignment: Alignment.centerLeft,
|
||||||
|
padding: fieldPadding,
|
||||||
|
decoration:
|
||||||
|
widget.isReadOnly ? disabledFieldDecoration : BoxDecoration( color: whiteColor , borderRadius: BorderRadius.circular(6.0), boxShadow: [
|
||||||
|
inputShadowBox
|
||||||
|
]),
|
||||||
|
child: Row(
|
||||||
|
children: <Widget>[
|
||||||
|
GestureDetector(
|
||||||
|
onTap: () {
|
||||||
|
if (isSearch) {
|
||||||
|
widget.fieldFocusNode!.requestFocus();
|
||||||
|
} else {
|
||||||
|
setState(() {
|
||||||
|
isSearch = !isSearch;
|
||||||
|
});
|
||||||
|
FocusScope.of(context)
|
||||||
|
.requestFocus(new FocusNode()); //remove focus
|
||||||
|
WidgetsBinding.instance!.addPostFrameCallback(
|
||||||
|
(_) => widget.controller.clear()); // clear content
|
||||||
|
}
|
||||||
|
},
|
||||||
|
child: widget.search
|
||||||
|
? Container(
|
||||||
|
width: fieldHeight,
|
||||||
|
height: fieldHeight,
|
||||||
|
alignment: Alignment.center,
|
||||||
|
child: Icon(isSearch ? Icons.search : Icons.search_off,
|
||||||
|
color: placeholderColor))
|
||||||
|
: Container(),
|
||||||
|
),
|
||||||
|
Expanded(
|
||||||
|
child: TextFormField(
|
||||||
|
style: TextStyle(
|
||||||
|
color: textColor,
|
||||||
|
fontSize: widget.smallVersion
|
||||||
|
? ScreenUtil().setSp(12)
|
||||||
|
: ScreenUtil().setSp(15)),
|
||||||
|
controller: widget.controller,
|
||||||
|
keyboardType: widget.textInputType,
|
||||||
|
focusNode: widget.fieldFocusNode,
|
||||||
|
textInputAction: widget.textInputAction,
|
||||||
|
maxLines: widget.multiline ? null : 1,
|
||||||
|
onChanged: widget.onChanged,
|
||||||
|
initialValue: widget.initialValue,
|
||||||
|
inputFormatters:
|
||||||
|
widget.formatter != null ? [widget.formatter!] : null,
|
||||||
|
onEditingComplete: () {
|
||||||
|
if (widget.enterPressed != null) {
|
||||||
|
FocusScope.of(context).requestFocus(FocusNode());
|
||||||
|
widget.enterPressed!();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onFieldSubmitted: (value) {
|
||||||
|
if (widget.nextFocusNode != null) {
|
||||||
|
widget.nextFocusNode!.requestFocus();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
obscureText: isPassword,
|
||||||
|
readOnly: widget.isReadOnly,
|
||||||
|
decoration: InputDecoration(
|
||||||
|
hintText: widget.placeholder,
|
||||||
|
filled: true,
|
||||||
|
fillColor: whiteColor,
|
||||||
|
border: InputBorder.none,
|
||||||
|
suffixText: widget.suffixText,
|
||||||
|
hintStyle: TextStyle(
|
||||||
|
fontSize: widget.smallVersion
|
||||||
|
? ScreenUtil().setSp(12)
|
||||||
|
: ScreenUtil().setSp(15),
|
||||||
|
color: placeholderColor)),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
GestureDetector(
|
||||||
|
onTap: () => setState(() {
|
||||||
|
isPassword = !isPassword;
|
||||||
|
}),
|
||||||
|
child: widget.password
|
||||||
|
? Container(
|
||||||
|
width: fieldHeight,
|
||||||
|
height: fieldHeight,
|
||||||
|
alignment: Alignment.center,
|
||||||
|
child: Icon(
|
||||||
|
isPassword
|
||||||
|
? Icons.visibility
|
||||||
|
: Icons.visibility_off,
|
||||||
|
color: textColor))
|
||||||
|
: Container(),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
if (widget.validationMessage != null)
|
||||||
|
NoteText(
|
||||||
|
widget.validationMessage ?? '',
|
||||||
|
color: dangerColor,
|
||||||
|
),
|
||||||
|
if (widget.additionalNote != null) verticalSpace(5),
|
||||||
|
if (widget.additionalNote != null)
|
||||||
|
NoteText(widget.additionalNote ?? ''),
|
||||||
|
verticalSpaceSmall
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -2,11 +2,11 @@ import 'package:flutter/material.dart';
|
||||||
import 'package:satu/shared/app_colors.dart';
|
import 'package:satu/shared/app_colors.dart';
|
||||||
|
|
||||||
class NoteText extends StatelessWidget {
|
class NoteText extends StatelessWidget {
|
||||||
|
const NoteText(this.text, {this.textAlign, this.color, this.fontSize});
|
||||||
final String text;
|
final String text;
|
||||||
final TextAlign? textAlign;
|
final TextAlign? textAlign;
|
||||||
final Color? color;
|
final Color? color;
|
||||||
final double? fontSize;
|
final double? fontSize;
|
||||||
const NoteText(this.text, {this.textAlign, this.color, this.fontSize});
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
|
|
|
||||||
|
|
@ -18,20 +18,20 @@ class ProductTitleWidget extends StatelessWidget {
|
||||||
children: [
|
children: [
|
||||||
Text(
|
Text(
|
||||||
name,
|
name,
|
||||||
style: TextStyle(fontSize: 12.sp, color: textColor),
|
style: TextStyle(fontSize: 14.sp, color: textColor),
|
||||||
overflow: TextOverflow.ellipsis,
|
overflow: TextOverflow.ellipsis,
|
||||||
maxLines: 2,
|
maxLines: 2,
|
||||||
),
|
),
|
||||||
verticalSpaceTiny,
|
verticalSpaceTiny,
|
||||||
if (ean != null)
|
if (ean != null)
|
||||||
Text(
|
Text(
|
||||||
'Штрих-код: ${ean}',
|
'Штрих-код: $ean',
|
||||||
style: TextStyle(color: placeholderColor, fontSize: 8.sp),
|
style: TextStyle(color: placeholderColor, fontSize: 10.sp),
|
||||||
),
|
),
|
||||||
if (categoryName != null)
|
if (categoryName != null)
|
||||||
Text(
|
Text(
|
||||||
'Категория: ${categoryName}',
|
'Категория: $categoryName',
|
||||||
style: TextStyle(color: placeholderColor, fontSize: 8.sp),
|
style: TextStyle(color: placeholderColor, fontSize: 10.sp),
|
||||||
)
|
)
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue