Files
smooth-app/packages/smooth_app/lib/knowledge_panel/knowledge_panels_builder.dart
monsieurtanuki 30be3388a4 feat: 4058 - expand/collapse for additional ecoscore fields (#4071)
* feat: 4058 - expand/collapse for additional ecoscore fields

New file:
* `product_field_editor.dart`: Helper class about product fields.

Impacted files:
* `add_new_product_page.dart`: added origins, ingredients, labels and packaging in option with expand/collapse; refactored using new classes around `ProductFieldEditor`
* `add_ocr_button.dart`: refactored using new class `ProductFieldOcrEditor`
* `add_packaging_button.dart`: refactored using new class `ProductFieldPackagingEditor
* `app_en.arb`: added one label for "additional ecoscore fields"
* `app_fr.arb`: added one label for "additional ecoscore fields"
* `edit_ocr_page.dart`: renamed from `edit_ingredients_page.dart`
* `edit_product_page.dart`: refactored using new classes `ProductFieldDetailsEditor`, `ProductFieldOcrIngredientEditor`, `ProductFieldPackagingEditor` and `ProductFieldOcrPackagingEditor`
* `knowledge_panel_action_card.dart`: minor refactoring
* `knowledge_panels_builder.dart`: minor refactoring
* `simple_input_page_helpers.dart`: added method `isPopulated`; minor refactoring
* `summary_card.dart`: refactored using new class `ProductFieldDetailsEditor`

* feat: 4058 - format

* feat: 4058 - refactoring

Impacted files:
* `add_simple_input_button.dart`: removed useless parameters; now uses `ProductFieldSimpleEditor`
* `edit_product_page.dart`: now uses `ProductFieldSimpleEditor`
* `product_field_editor.dart`: moved `edit` code from `simple_input_page_helpers.dart`
* `simple_input_page_helpers.dart`: moved code to `product_field_editor.dart`
2023-06-04 10:25:06 +02:00

141 lines
4.7 KiB
Dart

import 'package:flutter/material.dart';
import 'package:openfoodfacts/openfoodfacts.dart';
import 'package:provider/provider.dart';
import 'package:smooth_app/data_models/user_preferences.dart';
import 'package:smooth_app/generic_lib/design_constants.dart';
import 'package:smooth_app/knowledge_panel/knowledge_panels/knowledge_panel_element_card.dart';
import 'package:smooth_app/pages/preferences/user_preferences_dev_mode.dart';
import 'package:smooth_app/pages/product/add_nutrition_button.dart';
import 'package:smooth_app/pages/product/add_ocr_button.dart';
import 'package:smooth_app/pages/product/product_field_editor.dart';
import 'package:smooth_app/services/smooth_services.dart';
// TODO(monsieurtanuki): rename without "Widget", like the file: KnowledgePanelsBuilder?
/// "Knowledge Panel" widget.
class KnowledgePanelWidget {
const KnowledgePanelWidget._();
static List<Widget> getChildren(
BuildContext context, {
required KnowledgePanelElement panelElement,
required Product product,
required bool onboardingMode,
}) {
final String? panelId = panelElement.panelElement?.panelId;
final KnowledgePanel? rootPanel = panelId == null
? null
: KnowledgePanelWidget.getKnowledgePanel(product, panelId);
// [knowledgePanelElementWidgets] are a set of widgets inside the root panel.
final List<Widget> children = <Widget>[];
if (rootPanel != null) {
children.add(
Padding(
padding: const EdgeInsets.symmetric(
vertical: VERY_SMALL_SPACE,
horizontal: SMALL_SPACE,
),
child: Text(
rootPanel.titleElement!.title,
style: Theme.of(context).textTheme.displaySmall,
),
),
);
for (final KnowledgePanelElement knowledgePanelElement
in rootPanel.elements ?? <KnowledgePanelElement>[]) {
children.add(
KnowledgePanelElementCard(
knowledgePanelElement: knowledgePanelElement,
product: product,
isInitiallyExpanded: false,
),
);
}
}
if (!onboardingMode) {
if (panelId == 'health_card') {
final bool nutritionAddOrUpdate = product.statesTags?.contains(
ProductState.NUTRITION_FACTS_COMPLETED.toBeCompletedTag) ??
false;
if (nutritionAddOrUpdate) {
children.add(AddNutritionButton(product));
}
final bool needEditIngredients = context
.read<UserPreferences>()
.getFlag(UserPreferencesDevMode
.userPreferencesFlagEditIngredients) ??
false;
if ((product.ingredientsText == null ||
product.ingredientsText!.isEmpty) &&
needEditIngredients) {
// When the flag is removed, this should be the following:
// if (product.statesTags?.contains('en:ingredients-to-be-completed') ?? false) {
children.add(
AddOcrButton(
product: product,
editor: ProductFieldOcrIngredientEditor(),
),
);
}
}
}
if (children.isEmpty) {
Logs.e(
'Unexpected empty panel data for product "${product.barcode}" and panelId "$panelId"');
}
return children;
}
/// Returns all the panel elements, in option only the one matching [panelId].
static List<KnowledgePanelElement> getPanelElements(
final Product product, {
final String? panelId,
}) {
final List<KnowledgePanelElement> result = <KnowledgePanelElement>[];
final KnowledgePanel? root =
KnowledgePanelWidget.getKnowledgePanel(product, 'root');
if (root == null) {
return result;
}
if (root.elements == null) {
return result;
}
for (final KnowledgePanelElement panelElement in root.elements!) {
if (panelElement.elementType != KnowledgePanelElementType.PANEL) {
continue;
}
// no filter
if (panelId == null) {
result.add(panelElement);
} else {
if (panelId == panelElement.panelElement!.panelId) {
result.add(panelElement);
return result;
}
}
}
return result;
}
static KnowledgePanel? getKnowledgePanel(
final Product product,
final String panelId,
) =>
product.knowledgePanels?.panelIdToPanelMap[panelId];
/// Returns the unique panel element that matches [panelId], or `null`.
static KnowledgePanelElement? getPanelElement(
final Product product,
final String panelId,
) {
final List<KnowledgePanelElement> elements = getPanelElements(
product,
panelId: panelId,
);
if (elements.length != 1) {
return null;
}
return elements.first;
}
}