Skip to content

Commit

Permalink
feat: 5403 - improvements for "price adding"
Browse files Browse the repository at this point in the history
Impacted files:
* `app_en.arb`: added a "remember my choice" and a "barcode already there" labels
* `app_fr.arb`: added a "remember my choice" and a "barcode already there" labels
* `price_amount_card.dart`: now using a focus node and a `key`; stronger resilience
* `price_amount_field.dart`: now using a focus node
* `price_amount_model.dart`: minor refactoring
* `price_model.dart`: new `getBarcodes` method
* `price_product_search_page.dart`: now managing a list of existing barcodes; now storing at session level the answer of the "server look-up?" question
* `product_price_add_page.dart`: now manages a focus on the latest added product, and keys for item deletion; not displaying the "add product" button if irrelevant
  • Loading branch information
monsieurtanuki committed Jun 18, 2024
1 parent b9f83c4 commit a2d8c76
Show file tree
Hide file tree
Showing 8 changed files with 192 additions and 74 deletions.
13 changes: 13 additions & 0 deletions packages/smooth_app/lib/l10n/app_en.arb
Original file line number Diff line number Diff line change
Expand Up @@ -1726,6 +1726,15 @@
}
},
"prices_barcode_reader_action": "Barcode reader",
"prices_barcode_already": "Barcode {barcode} is already in the list!",
"@prices_barcode_already": {
"description": "Validation error message about barcode already being in the barcode list",
"placeholders": {
"barcode": {
"type": "String"
}
}
},
"prices_view_prices": "View the prices",
"prices_list_length_one_page": "{count,plural, =0{No price yet} =1{Only one price} other{All {count} prices}}",
"@prices_list_length_one_page": {
Expand Down Expand Up @@ -2354,6 +2363,10 @@
"@image_edit_url_error": {
"description": "Error message, when editing image fails, due to missing url."
},
"remember_my_choice_session": "Remember my choice for the current session",
"@remember_my_choice_session": {
"description": "Checkbox label when we want to remember the choice"
},
"user_picture_source_remember": "Remember my choice",
"@user_picture_source_remember": {
"description": "Checkbox label when select a picture source"
Expand Down
13 changes: 13 additions & 0 deletions packages/smooth_app/lib/l10n/app_fr.arb
Original file line number Diff line number Diff line change
Expand Up @@ -1704,6 +1704,15 @@
}
}
},
"prices_barcode_already": "Le code-barres {barcode} fait déjà partie de la liste !",
"@prices_barcode_already": {
"description": "Validation error message about barcode already being in the barcode list",
"placeholders": {
"barcode": {
"type": "String"
}
}
},
"prices_list_length_many_pages": "{pageSize} prix les plus récents (total : {total})",
"@prices_list_length_many_pages": {
"description": "Number of prices for one-page result",
Expand Down Expand Up @@ -2317,6 +2326,10 @@
"@image_edit_url_error": {
"description": "Error message, when editing image fails, due to missing url."
},
"remember_my_choice_session": "Mémoriser mon choix pour la session en cours",
"@remember_my_choice_session": {
"description": "Checkbox label when we want to remember the choice"
},
"user_picture_source_remember": "Mémoriser mon choix",
"@user_picture_source_remember": {
"description": "Checkbox label when select a picture source"
Expand Down
52 changes: 33 additions & 19 deletions packages/smooth_app/lib/pages/prices/price_amount_card.dart
Original file line number Diff line number Diff line change
Expand Up @@ -12,19 +12,19 @@ import 'package:smooth_app/pages/prices/price_product_search_page.dart';

/// Card that displays the amounts (discounted or not) for price adding.
class PriceAmountCard extends StatefulWidget {
PriceAmountCard({
const PriceAmountCard({
required this.priceModel,
required this.index,
required this.refresh,
}) : model = priceModel.priceAmountModels[index],
total = priceModel.priceAmountModels.length;
this.focusNode,
super.key,
});

final PriceModel priceModel;
final PriceAmountModel model;
final int index;
final int total;
// TODO(monsieurtanuki): not elegant, the display was not refreshed when removing an item
final VoidCallback refresh;
final FocusNode? focusNode;

@override
State<PriceAmountCard> createState() => _PriceAmountCardState();
Expand All @@ -35,22 +35,33 @@ class _PriceAmountCardState extends State<PriceAmountCard> {
final TextEditingController _controllerWithoutDiscount =
TextEditingController();

@override
void initState() {
super.initState();
_controllerPaid.text = _model.paidPrice;
_controllerWithoutDiscount.text = _model.priceWithoutDiscount;
}

PriceAmountModel get _model =>
widget.priceModel.priceAmountModels[widget.index];
int get _total => widget.priceModel.priceAmountModels.length;

@override
Widget build(BuildContext context) {
final AppLocalizations appLocalizations = AppLocalizations.of(context);
final bool isEmpty = widget.model.product.barcode.isEmpty;
final bool isEmpty = _model.product.barcode.isEmpty;
return SmoothCard(
child: Column(
children: <Widget>[
Text(
'${appLocalizations.prices_amount_subtitle}'
'${widget.total == 1 ? '' : ' (${widget.index + 1}/${widget.total})'}',
'${_total == 1 ? '' : ' (${widget.index + 1}/$_total)'}',
),
PriceProductListTile(
product: widget.model.product,
product: _model.product,
trailingIconData: isEmpty
? Icons.edit
: widget.total == 1
: _total == 1
? null
: Icons.clear,
onPressed: isEmpty
Expand All @@ -59,15 +70,18 @@ class _PriceAmountCardState extends State<PriceAmountCard> {
await Navigator.of(context).push<PriceMetaProduct>(
MaterialPageRoute<PriceMetaProduct>(
builder: (BuildContext context) =>
const PriceProductSearchPage(),
PriceProductSearchPage(
barcodes: widget.priceModel.getBarcodes(),
),
),
);
if (product == null) {
return;
}
setState(() => widget.model.product = product);
_model.product = product;
widget.refresh.call();
}
: widget.total == 1
: _total == 1
? null
: () {
widget.priceModel.priceAmountModels
Expand All @@ -76,32 +90,32 @@ class _PriceAmountCardState extends State<PriceAmountCard> {
},
),
SmoothLargeButtonWithIcon(
icon: widget.model.promo
? Icons.check_box
: Icons.check_box_outline_blank,
icon:
_model.promo ? Icons.check_box : Icons.check_box_outline_blank,
text: appLocalizations.prices_amount_is_discounted,
onPressed: () => setState(
() => widget.model.promo = !widget.model.promo,
() => _model.promo = !_model.promo,
),
),
const SizedBox(height: SMALL_SPACE),
Row(
children: <Widget>[
Expanded(
child: PriceAmountField(
focusNode: widget.focusNode,
controller: _controllerPaid,
isPaidPrice: true,
model: widget.model,
model: _model,
),
),
const SizedBox(width: LARGE_SPACE),
Expanded(
child: !widget.model.promo
child: !_model.promo
? Container()
: PriceAmountField(
controller: _controllerWithoutDiscount,
isPaidPrice: false,
model: widget.model,
model: _model,
),
),
],
Expand Down
4 changes: 3 additions & 1 deletion packages/smooth_app/lib/pages/prices/price_amount_field.dart
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,14 @@ class PriceAmountField extends StatelessWidget {
required this.model,
required this.isPaidPrice,
required this.controller,
this.focusNode,
});

final PriceAmountModel model;
final bool isPaidPrice;
final TextEditingController controller;
final FocusNode? focusNode;

// TODO(monsieurtanuki): TextInputAction + focus
static const TextInputType _priceTextInputType =
TextInputType.numberWithOptions(
signed: false,
Expand All @@ -26,6 +27,7 @@ class PriceAmountField extends StatelessWidget {
Widget build(BuildContext context) {
final AppLocalizations appLocalizations = AppLocalizations.of(context);
return SmoothTextFormField(
focusNode: focusNode,
type: TextFieldTypes.PLAIN_TEXT,
controller: controller,
hintText: !isPaidPrice
Expand Down
14 changes: 5 additions & 9 deletions packages/smooth_app/lib/pages/prices/price_amount_model.dart
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,8 @@ class PriceAmountModel {

PriceMetaProduct product;

String _paidPrice = '';
String _priceWithoutDiscount = '';

set paidPrice(final String value) => _paidPrice = value;

set priceWithoutDiscount(final String value) => _priceWithoutDiscount = value;
String paidPrice = '';
String priceWithoutDiscount = '';

late double _checkedPaidPrice;
double? _checkedPriceWithoutDiscount;
Expand All @@ -37,11 +33,11 @@ class PriceAmountModel {
if (product.barcode.isEmpty) {
return appLocalizations.prices_amount_no_product;
}
_checkedPaidPrice = validateDouble(_paidPrice)!;
_checkedPaidPrice = validateDouble(paidPrice)!;
_checkedPriceWithoutDiscount = null;
if (promo) {
if (_priceWithoutDiscount.isNotEmpty) {
_checkedPriceWithoutDiscount = validateDouble(_priceWithoutDiscount);
if (priceWithoutDiscount.isNotEmpty) {
_checkedPriceWithoutDiscount = validateDouble(priceWithoutDiscount);
if (_checkedPriceWithoutDiscount == null) {
return appLocalizations.prices_amount_price_incorrect;
}
Expand Down
8 changes: 8 additions & 0 deletions packages/smooth_app/lib/pages/prices/price_model.dart
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,14 @@ class PriceModel with ChangeNotifier {

final List<PriceAmountModel> priceAmountModels;

List<String> getBarcodes() {
final List<String> result = <String>[];
for (final PriceAmountModel priceAmountModel in priceAmountModels) {
result.add(priceAmountModel.product.barcode);
}
return result;
}

CropParameters? _cropParameters;

CropParameters? get cropParameters => _cropParameters;
Expand Down
Loading

0 comments on commit a2d8c76

Please sign in to comment.