Files
smooth-app/packages/smooth_app/lib/knowledge_panel/knowledge_panels_builder.dart
Marvin M 21aa2c2539 fix: Dont show arrow if there is no subpanel (#2006)
* refactor: Moved files

* Refactor

* fix: Dont show arrow when not clickable anymore [knowledge_panel]

* fix: Dont show arrow when not clickable anymore [score_card]

* Change icon

* Update score_card.dart

* Update knowledge_panel_summary_card.dart
2022-05-26 19:17:42 +02:00

198 lines
6.9 KiB
Dart

import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import 'package:openfoodfacts/model/KnowledgePanel.dart';
import 'package:openfoodfacts/model/KnowledgePanelElement.dart';
import 'package:openfoodfacts/model/KnowledgePanels.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/helpers/product_cards_helper.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/edit_ingredients_page.dart';
import 'package:smooth_app/pages/product/nutrition_page_loaded.dart';
import 'package:smooth_app/pages/product/ordered_nutrients_cache.dart';
/// Builds "knowledge panels" panels.
///
/// Panels display large data like all health data or environment data.
/// This is to be used publicly in the app
class KnowledgePanelsBuilder {
const KnowledgePanelsBuilder({
this.setState,
this.refreshProductCallback,
});
/// Would for instance refresh the product page.
final VoidCallback? setState;
/// Callback to refresh the product when necessary.
final Function(BuildContext)? refreshProductCallback;
/// Builds all panels.
///
/// Typical use case: product page.
List<Widget> buildAll(
KnowledgePanels knowledgePanels, {
final Product? product,
final BuildContext? context,
}) {
final List<Widget> rootPanelWidgets = <Widget>[];
if (knowledgePanels.panelIdToPanelMap['root'] == null) {
return rootPanelWidgets;
}
if (knowledgePanels.panelIdToPanelMap['root']!.elements == null) {
return rootPanelWidgets;
}
for (final KnowledgePanelElement panelElement
in knowledgePanels.panelIdToPanelMap['root']!.elements!) {
if (panelElement.elementType != KnowledgePanelElementType.PANEL) {
continue;
}
rootPanelWidgets.add(
_buildPanel(
panelElement,
knowledgePanels,
context: context,
product: product,
),
);
}
return rootPanelWidgets;
}
/// Builds a single panel, if available.
///
/// Typical use case so far: onboarding, where we focus on one panel only.
Widget? buildSingle(
final KnowledgePanels knowledgePanels,
final String panelId, {
final BuildContext? context,
}) {
if (knowledgePanels.panelIdToPanelMap['root'] == null) {
return null;
}
if (knowledgePanels.panelIdToPanelMap['root']!.elements == null) {
return null;
}
for (final KnowledgePanelElement panelElement
in knowledgePanels.panelIdToPanelMap['root']!.elements!) {
if (panelElement.elementType != KnowledgePanelElementType.PANEL) {
continue;
}
if (panelId != panelElement.panelElement!.panelId) {
continue;
}
return _buildPanel(
panelElement,
knowledgePanels,
context: context,
);
}
return null;
}
Widget _buildPanel(
final KnowledgePanelElement panelElement,
final KnowledgePanels knowledgePanels, {
final Product? product,
final BuildContext? context,
}) {
final String panelId = panelElement.panelElement!.panelId;
final KnowledgePanel rootPanel =
knowledgePanels.panelIdToPanelMap[panelId]!;
// [knowledgePanelElementWidgets] are a set of widgets inside the root panel.
final List<Widget> knowledgePanelElementWidgets = <Widget>[];
if (context != null) {
knowledgePanelElementWidgets.add(
Padding(
padding: const EdgeInsets.symmetric(vertical: VERY_SMALL_SPACE),
child: Text(
rootPanel.titleElement!.title,
style: Theme.of(context).textTheme.headline3,
),
),
);
}
for (final KnowledgePanelElement knowledgePanelElement
in rootPanel.elements ?? <KnowledgePanelElement>[]) {
knowledgePanelElementWidgets.add(
KnowledgePanelElementCard(
knowledgePanelElement: knowledgePanelElement,
allPanels: knowledgePanels,
),
);
}
if (product != null && context != null) {
if (panelId == 'health_card') {
final bool nutritionAddOrUpdate = product.statesTags
?.contains('en:nutrition-facts-to-be-completed') ??
false;
final AppLocalizations appLocalizations = AppLocalizations.of(context);
if (nutritionAddOrUpdate) {
knowledgePanelElementWidgets.add(
addPanelButton(
nutritionAddOrUpdate
? appLocalizations.score_add_missing_nutrition_facts
: appLocalizations.score_update_nutrition_facts,
iconData: nutritionAddOrUpdate ? Icons.add : Icons.edit,
onPressed: () async {
final OrderedNutrientsCache? cache =
await OrderedNutrientsCache.getCache(context);
if (cache == null) {
return;
}
//ignore: use_build_context_synchronously
final bool? refreshed = await Navigator.push<bool>(
context,
MaterialPageRoute<bool>(
builder: (BuildContext context) => NutritionPageLoaded(
product,
cache.orderedNutrients,
),
),
);
if (refreshed ?? false) {
setState?.call();
}
// TODO(monsieurtanuki): refresh the data if changed
},
),
);
}
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) {
knowledgePanelElementWidgets.add(
addPanelButton(
appLocalizations.score_add_missing_ingredients,
onPressed: () async => Navigator.push<bool>(
context,
MaterialPageRoute<bool>(
builder: (BuildContext context) => EditIngredientsPage(
product: product,
refreshProductCallback: refreshProductCallback,
),
),
),
),
);
}
}
}
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: knowledgePanelElementWidgets,
);
}
}