diff --git a/packages/smooth_app/assets/product/product_completed_graphic_dark.svg b/packages/smooth_app/assets/product/product_completed_graphic_dark.svg
new file mode 100644
index 00000000000..1926c038cae
--- /dev/null
+++ b/packages/smooth_app/assets/product/product_completed_graphic_dark.svg
@@ -0,0 +1,17 @@
+
\ No newline at end of file
diff --git a/packages/smooth_app/assets/product/product_completed_graphic_light.svg b/packages/smooth_app/assets/product/product_completed_graphic_light.svg
new file mode 100644
index 00000000000..f2a1cac5ddf
--- /dev/null
+++ b/packages/smooth_app/assets/product/product_completed_graphic_light.svg
@@ -0,0 +1,17 @@
+
\ No newline at end of file
diff --git a/packages/smooth_app/lib/generic_lib/widgets/smooth_card.dart b/packages/smooth_app/lib/generic_lib/widgets/smooth_card.dart
index 735f74f6480..1074be7f7b6 100644
--- a/packages/smooth_app/lib/generic_lib/widgets/smooth_card.dart
+++ b/packages/smooth_app/lib/generic_lib/widgets/smooth_card.dart
@@ -20,6 +20,7 @@ class SmoothCard extends StatelessWidget {
this.elevation = 8,
this.borderRadius,
this.ignoreDefaultSemantics = false,
+ this.clipBehavior,
});
const SmoothCard.angular({
@@ -32,6 +33,7 @@ class SmoothCard extends StatelessWidget {
this.padding = const EdgeInsets.all(5.0),
this.elevation = 8,
this.ignoreDefaultSemantics = false,
+ this.clipBehavior,
}) : borderRadius = ANGULAR_BORDER_RADIUS;
const SmoothCard.flat({
@@ -47,6 +49,7 @@ class SmoothCard extends StatelessWidget {
this.elevation = 0,
this.borderRadius,
this.ignoreDefaultSemantics = false,
+ this.clipBehavior,
});
final Widget child;
@@ -56,6 +59,7 @@ class SmoothCard extends StatelessWidget {
final BorderRadiusGeometry? borderRadius;
final double elevation;
final bool ignoreDefaultSemantics;
+ final Clip? clipBehavior;
@override
Widget build(BuildContext context) {
@@ -80,6 +84,7 @@ class SmoothCard extends StatelessWidget {
(Theme.of(context).brightness == Brightness.light
? Colors.white
: Colors.black),
+ clipBehavior: clipBehavior ?? Clip.none,
child: result,
);
diff --git a/packages/smooth_app/lib/l10n/app_en.arb b/packages/smooth_app/lib/l10n/app_en.arb
index edeb0b1a73b..00650ce193f 100644
--- a/packages/smooth_app/lib/l10n/app_en.arb
+++ b/packages/smooth_app/lib/l10n/app_en.arb
@@ -622,6 +622,21 @@
"new_product_desc_nova_unknown": "Food processing level unknown",
"new_product_title_pictures": "Let's take some pictures!",
"new_product_title_misc": "And some basic data…",
+ "new_product_done_msg": "Thanks for your contribution “{username}”!",
+ "@new_product_done_msg": {
+ "description": "Thank you message on the end of new producut page, after finish adding a new product.",
+ "placeholders": {
+ "username": {
+ "type": "String",
+ "example": "Bob"
+ }
+ }
+ },
+ "new_product_done_msg_no_user": "Thanks for your contribution!",
+ "new_product_done_button_label": "Discover the completed product",
+ "@new_product_done_button_label": {
+ "description": "Button at the end of new product page, that takes you to completed product"
+ },
"hey_incomplete_product_message": "Tap to answer 3 questions NOW to compute Nutri-Score, Eco-Score & Ultra-processing (NOVA)!",
"nutritional_facts_photo_uploaded": "Nutrition facts photo uploaded",
"@nutritional_facts_photo_uploaded": {},
diff --git a/packages/smooth_app/lib/pages/product/add_new_product_page.dart b/packages/smooth_app/lib/pages/product/add_new_product_page.dart
index 4e98f23969c..f5fb3e83a12 100644
--- a/packages/smooth_app/lib/pages/product/add_new_product_page.dart
+++ b/packages/smooth_app/lib/pages/product/add_new_product_page.dart
@@ -2,6 +2,7 @@ import 'dart:io';
import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
+import 'package:flutter_svg/flutter_svg.dart';
import 'package:matomo_tracker/matomo_tracker.dart';
import 'package:openfoodfacts/openfoodfacts.dart';
import 'package:provider/provider.dart';
@@ -10,13 +11,16 @@ import 'package:smooth_app/data_models/product_list.dart';
import 'package:smooth_app/data_models/up_to_date_mixin.dart';
import 'package:smooth_app/database/dao_product_list.dart';
import 'package:smooth_app/database/local_database.dart';
+import 'package:smooth_app/generic_lib/buttons/smooth_simple_button.dart';
import 'package:smooth_app/generic_lib/design_constants.dart';
import 'package:smooth_app/generic_lib/dialogs/smooth_alert_dialog.dart';
import 'package:smooth_app/generic_lib/widgets/smooth_card.dart';
import 'package:smooth_app/helpers/analytics_helper.dart';
import 'package:smooth_app/helpers/image_field_extension.dart';
import 'package:smooth_app/helpers/product_cards_helper.dart';
+import 'package:smooth_app/helpers/user_management_helper.dart';
import 'package:smooth_app/pages/image_crop_page.dart';
+import 'package:smooth_app/pages/navigator/app_navigator.dart';
import 'package:smooth_app/pages/product/add_new_product_helper.dart';
import 'package:smooth_app/pages/product/common/product_dialog_helper.dart';
import 'package:smooth_app/pages/product/nutrition_page_loaded.dart';
@@ -213,6 +217,13 @@ class _AddNewProductPageState extends State
_buildCard(_getEcoscoreRows(context)),
_buildCard(_getNovaRows(context)),
if (widget.displayMisc) _buildCard(_getMiscRows(context)),
+ if (_isPopulated)
+ _buildDoneCard(
+ context,
+ onDoneClick: () => AppNavigator.of(context).push(
+ AppRoutes.PRODUCT(barcode),
+ extra: widget.product),
+ ),
const SizedBox(height: MINIMUM_TOUCH_SIZE),
],
),
@@ -468,4 +479,89 @@ class _AddNewProductPageState extends State
disabled: disabled,
isLoggedInMandatory: widget.isLoggedInMandatory,
);
+
+ Widget _buildDoneCard(final BuildContext context,
+ {required final VoidCallback onDoneClick}) {
+ final AppLocalizations localizations = AppLocalizations.of(context);
+ final bool isDark = Theme.of(context).brightness == Brightness.dark;
+
+ return SizedBox(
+ width: double.infinity,
+ child: SmoothCard(
+ clipBehavior: Clip.antiAliasWithSaveLayer,
+ color: Theme.of(context).colorScheme.secondary,
+ child: Column(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ Padding(
+ padding: const EdgeInsets.all(SMALL_SPACE),
+ child: Text(
+ _createDoneMessage(localizations),
+ style: Theme.of(context).textTheme.displaySmall,
+ ),
+ ),
+ Row(
+ children: [
+ Expanded(
+ child: Padding(
+ padding: const EdgeInsets.all(SMALL_SPACE),
+ child: SmoothSimpleButton(
+ onPressed: onDoneClick,
+ buttonColor: Colors.green[700],
+ child: Row(
+ mainAxisAlignment: MainAxisAlignment.spaceBetween,
+ children: [
+ Flexible(
+ child: Text(
+ localizations.new_product_done_button_label),
+ ),
+ const SizedBox(width: SMALL_SPACE),
+ const Icon(Icons.arrow_forward),
+ ],
+ ),
+ ),
+ ),
+ ),
+ const SizedBox(height: MEDIUM_SPACE),
+ Stack(
+ alignment: Alignment.bottomRight,
+ children: [
+ Align(
+ alignment: Alignment.topLeft,
+ widthFactor: 0.8,
+ heightFactor: 0.8,
+ child: SvgPicture.asset(
+ isDark
+ ? 'assets/product/product_completed_graphic_dark.svg'
+ : 'assets/product/product_completed_graphic_light.svg',
+ width: 70,
+ ),
+ ),
+ ],
+ ),
+ ],
+ ),
+ ],
+ ),
+ ),
+ );
+ }
+}
+
+String _createDoneMessage(AppLocalizations localizations) {
+ final String? name = _getRegisteredUserName();
+ if (name == null) {
+ return localizations.new_product_done_msg_no_user;
+ } else {
+ return localizations.new_product_done_msg(name);
+ }
+}
+
+String? _getRegisteredUserName() {
+ final String? userId = OpenFoodAPIConfiguration.globalUser?.userId;
+ if (userId == null || userId.isEmail) {
+ return null;
+ } else {
+ return userId;
+ }
}