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 @@ + + Artboard + + + + + Layer 1 + + + + + + + + + + \ 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 @@ + + Artboard + + + + + Layer 1 + + + + + + + + + + \ 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; + } }