Skip to content

Commit

Permalink
feat: 5988 - new "top price products" page (openfoodfacts#6310)
Browse files Browse the repository at this point in the history
* feat: 5988 - new "top price products" page

New file:
* `prices_products_page.dart`: Page that displays the top prices products.

Impacted files:
* `app_en.arb`: added 1 label for top product counts
* `price_product_widget.dart`: minor refactoring
* `product_prices_list.dart`: minor refactoring
* `pubspec.lock`: wtf
* `pubspec.yaml`: upgraded `openfoodfacts` to `3.19.0`
* `user_preferences_prices.dart`: link to new page `PricesProductsPage`

* Add new localization strings for product prices

---------

Co-authored-by: Pierre Slamich <[email protected]>
  • Loading branch information
monsieurtanuki and teolemon authored Jan 30, 2025
1 parent d8e1016 commit 0c9eadf
Show file tree
Hide file tree
Showing 7 changed files with 158 additions and 26 deletions.
16 changes: 16 additions & 0 deletions packages/smooth_app/lib/l10n/app_en.arb
Original file line number Diff line number Diff line change
Expand Up @@ -3845,5 +3845,21 @@
"product_footer_action_data_quality_tags": "Data quality",
"@product_footer_action_data_quality_tags": {
"description": "Action to view data quality warnings"
},
"all_search_prices_top_product_title": "Products with the most prices",
"@all_search_prices_top_product_title": {
"description": "Top price products: list tile title"
},
"prices_products_list_length_many_pages": "Top {pageSize} products (total: {total})",
"@prices_products_list_length_many_pages": {
"description": "Number of products for one-page result",
"placeholders": {
"pageSize": {
"type": "int"
},
"total": {
"type": "int"
}
}
}
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:openfoodfacts/openfoodfacts.dart';
import 'package:smooth_app/helpers/launch_url_helper.dart';
import 'package:smooth_app/pages/navigator/app_navigator.dart';
import 'package:smooth_app/pages/preferences/abstract_user_preferences.dart';
import 'package:smooth_app/pages/preferences/lazy_counter.dart';
Expand All @@ -14,6 +13,7 @@ import 'package:smooth_app/pages/prices/price_button.dart';
import 'package:smooth_app/pages/prices/price_user_button.dart';
import 'package:smooth_app/pages/prices/prices_locations_page.dart';
import 'package:smooth_app/pages/prices/prices_page.dart';
import 'package:smooth_app/pages/prices/prices_products_page.dart';
import 'package:smooth_app/pages/prices/prices_proofs_page.dart';
import 'package:smooth_app/pages/prices/prices_users_page.dart';
import 'package:smooth_app/pages/prices/product_price_add_page.dart';
Expand Down Expand Up @@ -121,9 +121,14 @@ class UserPreferencesPrices extends AbstractUserPreferences {
),
PriceButton.locationIconData,
),
_getPriceListTile(
_getListTile(
appLocalizations.all_search_prices_top_product_title,
'products',
() async => Navigator.of(context).push(
MaterialPageRoute<void>(
builder: (BuildContext context) => const PricesProductsPage(),
),
),
PriceButton.productIconData,
),
];
}
Expand All @@ -134,21 +139,6 @@ class UserPreferencesPrices extends AbstractUserPreferences {
AppRoutes.PREFERENCES(PreferencePageType.PRICES),
);

UserPreferencesItem _getPriceListTile(
final String title,
final String path,
) =>
_getListTile(
title,
() async => LaunchUrlHelper.launchURL(
OpenPricesAPIClient.getUri(
path: path,
uriHelper: ProductQuery.uriPricesHelper,
).toString(),
),
Icons.open_in_new,
);

UserPreferencesItem _getListTile(
final String title,
final VoidCallback onTap,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,11 @@ import 'package:smooth_app/pages/prices/prices_page.dart';
class PriceProductWidget extends StatelessWidget {
const PriceProductWidget(
this.priceProduct, {
required this.model,
required this.enableCountButton,
});

final PriceProduct priceProduct;
final GetPricesModel model;
final bool enableCountButton;

@override
Widget build(BuildContext context) {
Expand Down Expand Up @@ -77,7 +77,7 @@ class PriceProductWidget extends StatelessWidget {
children: <Widget>[
PriceCountWidget(
count: priceCount,
onPressed: !model.enableCountButton
onPressed: !enableCountButton
? null
: () async {
final LocalDatabase localDatabase =
Expand Down
126 changes: 126 additions & 0 deletions packages/smooth_app/lib/pages/prices/prices_products_page.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import 'package:matomo_tracker/matomo_tracker.dart';
import 'package:openfoodfacts/openfoodfacts.dart';
import 'package:smooth_app/generic_lib/design_constants.dart';
import 'package:smooth_app/generic_lib/widgets/smooth_back_button.dart';
import 'package:smooth_app/generic_lib/widgets/smooth_card.dart';
import 'package:smooth_app/helpers/launch_url_helper.dart';
import 'package:smooth_app/pages/prices/price_product_widget.dart';
import 'package:smooth_app/query/product_query.dart';
import 'package:smooth_app/widgets/smooth_app_bar.dart';
import 'package:smooth_app/widgets/smooth_scaffold.dart';

/// Page that displays the top prices products.
class PricesProductsPage extends StatefulWidget {
const PricesProductsPage();

@override
State<PricesProductsPage> createState() => _PricesProductsPageState();
}

class _PricesProductsPageState extends State<PricesProductsPage>
with TraceableClientMixin {
late final Future<MaybeError<GetPriceProductsResult>> _products =
_showTopProducts();

// In this specific page, let's never try to go beyond the top 10.
// cf. https://github.com/openfoodfacts/smooth-app/pull/5383#issuecomment-2171117141
static const int _pageSize = 10;

@override
Widget build(BuildContext context) {
final AppLocalizations appLocalizations = AppLocalizations.of(context);
return SmoothScaffold(
appBar: SmoothAppBar(
centerTitle: false,
leading: const SmoothBackButton(),
title: Text(
appLocalizations.all_search_prices_top_product_title,
),
actions: <Widget>[
IconButton(
tooltip: appLocalizations.prices_app_button,
icon: const Icon(Icons.open_in_new),
onPressed: () async => LaunchUrlHelper.launchURL(
OpenPricesAPIClient.getUri(
path: 'products',
uriHelper: ProductQuery.uriPricesHelper,
).toString(),
),
),
],
),
body: FutureBuilder<MaybeError<GetPriceProductsResult>>(
future: _products,
builder: (
final BuildContext context,
final AsyncSnapshot<MaybeError<GetPriceProductsResult>> snapshot,
) {
if (snapshot.connectionState != ConnectionState.done) {
return const CircularProgressIndicator();
}
if (snapshot.hasError) {
return Text(snapshot.error!.toString());
}
// highly improbable
if (!snapshot.hasData) {
return const Text('no data');
}
if (snapshot.data!.isError) {
return Text(snapshot.data!.error!);
}
final GetPriceProductsResult result = snapshot.data!.value;
// highly improbable
if (result.items == null) {
return const Text('empty list');
}
final List<Widget> children = <Widget>[];

for (final PriceProduct item in result.items!) {
children.add(
SmoothCard(
child: PriceProductWidget(
item,
enableCountButton: true,
),
),
);
}
final AppLocalizations appLocalizations =
AppLocalizations.of(context);
final String title =
appLocalizations.prices_products_list_length_many_pages(
_pageSize,
result.total!,
);
children.insert(
0,
SmoothCard(child: ListTile(title: Text(title))),
);
// so that the last content gets not hidden by the FAB
children.add(
const SizedBox(height: 2 * MINIMUM_TOUCH_SIZE),
);
return ListView(
children: children,
);
},
),
);
}

static Future<MaybeError<GetPriceProductsResult>> _showTopProducts() async =>
OpenPricesAPIClient.getPriceProducts(
GetPriceProductsParameters()
..orderBy = <OrderBy<GetPriceProductsOrderField>>[
const OrderBy<GetPriceProductsOrderField>(
field: GetPriceProductsOrderField.priceCount,
ascending: false,
),
]
..pageSize = _pageSize
..pageNumber = 1,
uriHelper: ProductQuery.uriPricesHelper,
);
}
4 changes: 2 additions & 2 deletions packages/smooth_app/lib/pages/prices/product_prices_list.dart
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ class _ProductPricesListState extends State<ProductPricesList>
SmoothCard(
child: PriceProductWidget(
priceProduct,
model: widget.model,
enableCountButton: widget.model.enableCountButton,
),
),
);
Expand Down Expand Up @@ -116,7 +116,7 @@ class _ProductPricesListState extends State<ProductPricesList>
if (widget.model.displayEachProduct && priceProduct != null)
PriceProductWidget(
priceProduct,
model: widget.model,
enableCountButton: widget.model.enableCountButton,
),
PriceDataWidget(
price,
Expand Down
4 changes: 2 additions & 2 deletions packages/smooth_app/pubspec.lock
Original file line number Diff line number Diff line change
Expand Up @@ -1113,10 +1113,10 @@ packages:
dependency: "direct main"
description:
name: openfoodfacts
sha256: c0d85d236aebc874b694bb0b52c34cee2d0d68169cffcec0d006605c2014ea04
sha256: d23892da30f3cab7a767dcbfa894ed556ee44fa925b7c16f42305eb07880b84f
url: "https://pub.dev"
source: hosted
version: "3.18.1"
version: "3.19.0"
openfoodfacts_flutter_lints:
dependency: "direct dev"
description:
Expand Down
2 changes: 1 addition & 1 deletion packages/smooth_app/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ dependencies:
path: ../scanner/zxing


openfoodfacts: 3.18.1
openfoodfacts: 3.19.0
# openfoodfacts:
# path: ../../../openfoodfacts-dart

Expand Down

0 comments on commit 0c9eadf

Please sign in to comment.