From 3057181d5e9b59d368c37e6fe214021f2b32849b Mon Sep 17 00:00:00 2001 From: Tamara Slosarek Date: Tue, 27 Feb 2024 13:00:09 +0100 Subject: [PATCH] feat(#702): add legend of warning level indicators to report page * Moves "learn more about genetics" text to tooltip icon in title and refers to FAQ * Moves "learn more about genetics" item in FAQ further up * Increases Dart version to be able to safely use 'indexed' --- app/lib/common/widgets/page_scaffold.dart | 20 +++- app/lib/drug/widgets/tooltip_icon.dart | 7 +- app/lib/faq/constants.dart | 34 +++--- app/lib/l10n/app_en.arb | 8 +- app/lib/report/pages/report.dart | 137 ++++++++++++++-------- app/pubspec.yaml | 2 +- 6 files changed, 131 insertions(+), 77 deletions(-) diff --git a/app/lib/common/widgets/page_scaffold.dart b/app/lib/common/widgets/page_scaffold.dart index a913c53a..8f31f250 100644 --- a/app/lib/common/widgets/page_scaffold.dart +++ b/app/lib/common/widgets/page_scaffold.dart @@ -1,3 +1,4 @@ +import '../../drug/widgets/tooltip_icon.dart'; import '../module.dart'; EdgeInsets pagePadding() => EdgeInsets.only( @@ -5,10 +6,22 @@ EdgeInsets pagePadding() => EdgeInsets.only( right: PharMeTheme.defaultPagePadding, ); -Widget buildTitle(String text) { +Widget buildTitle(String text, { String? tooltipText }) { return FittedBox( fit: BoxFit.fitWidth, - child: Text(text, style: PharMeTheme.textTheme.headlineLarge), + child: Row( + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Text(text, style: PharMeTheme.textTheme.headlineLarge), + if (tooltipText.isNotNullOrBlank) Padding( + padding: EdgeInsets.only(left: PharMeTheme.smallSpace), + child: TooltipIcon( + tooltipText!, + size: PharMeTheme.textTheme.headlineLarge!.fontSize! * 0.8, + ), + ), + ] + ), ); } @@ -68,6 +81,7 @@ Scaffold pageScaffold({ Scaffold unscrollablePageScaffold({ required Widget body, String? title, + String? titleTooltip, String? barBottom, List? actions, Widget? drawer, @@ -83,7 +97,7 @@ Scaffold unscrollablePageScaffold({ leadingWidth: PharMeTheme.appBarTheme.leadingWidth, automaticallyImplyLeading: automaticallyImplyLeading, centerTitle: PharMeTheme.appBarTheme.centerTitle, - title: buildTitle(title), + title: buildTitle(title, tooltipText: titleTooltip), actions: actions, bottom: buildBarBottom(barBottom), scrolledUnderElevation: 0, diff --git a/app/lib/drug/widgets/tooltip_icon.dart b/app/lib/drug/widgets/tooltip_icon.dart index 3cf51131..44a83a7a 100644 --- a/app/lib/drug/widgets/tooltip_icon.dart +++ b/app/lib/drug/widgets/tooltip_icon.dart @@ -1,11 +1,10 @@ -import 'package:flutter/material.dart'; - import '../../common/module.dart'; class TooltipIcon extends StatelessWidget { - const TooltipIcon(this.message); + const TooltipIcon(this.message, { this.size = 16 }); final String message; + final double size; @override Widget build(BuildContext context) { @@ -14,7 +13,7 @@ class TooltipIcon extends StatelessWidget { margin: EdgeInsets.all(PharMeTheme.smallSpace), triggerMode: TooltipTriggerMode.tap, showDuration: const Duration(seconds: 3), - child: Icon(Icons.help_outline_rounded, size: 16), + child: Icon(Icons.help_outline_rounded, size: size), ); } } diff --git a/app/lib/faq/constants.dart b/app/lib/faq/constants.dart index 0fb79522..b56cd59d 100644 --- a/app/lib/faq/constants.dart +++ b/app/lib/faq/constants.dart @@ -36,23 +36,8 @@ final Map> faqList = { answer: 'Pharmacogenetics is important because it helps to predict those who will respond well to drugs and those who may have side effects. With this information we can better select the right drug and dose to avoid side effects.', ), - TextAnswerQuestion( - question: 'Which drugs are affected?', - answer: - 'Examples of affected drug classes include anti-clotting medications (like clopidogrel and warfarin), antidepressants (like sertraline, citalopram, and paroxetine), anti-cholesterol drugs (like simvastatin and atorvastatin), acid reducers (like pantoprazole and omeprazole), pain killers (like codeine, tramadol, and ibuprofen), antifungals (like voriconazole), drugs that suppress the immune system (like tacrolimus), and anti-cancer drugs (like fluorouracil and irinotecan). You can find out whether a certain drug is affected in the Search tab.', - ), - TextAnswerQuestion( - question: 'Will my results affect my family members?', - answer: - 'Yes, since this is a genetic test, it is possible that your results were passed down to you and your siblings from your parents and you will also pass them down to your children.', - ), - TextAnswerQuestion( - question: 'Who can I share my results with?', - answer: - 'We recommend that you share your results with your pharmacists, doctors, and close family members such as parents, siblings, and children.', - ), WidgetAnswerQuestion( - question: 'Where can I find out more about genetics?', + question: 'Where can I find out more about genetics in general?', answer: RichText(text: TextSpan( // context.l10n.genetic_information_text_part_1 text: 'If you would like to learn more about genetics, we recommend ', @@ -68,7 +53,22 @@ final Map> faqList = { ), ], )), - ) + ), + TextAnswerQuestion( + question: 'Which drugs are affected?', + answer: + 'Examples of affected drug classes include anti-clotting medications (like clopidogrel and warfarin), antidepressants (like sertraline, citalopram, and paroxetine), anti-cholesterol drugs (like simvastatin and atorvastatin), acid reducers (like pantoprazole and omeprazole), pain killers (like codeine, tramadol, and ibuprofen), antifungals (like voriconazole), drugs that suppress the immune system (like tacrolimus), and anti-cancer drugs (like fluorouracil and irinotecan). You can find out whether a certain drug is affected in the Search tab.', + ), + TextAnswerQuestion( + question: 'Will my results affect my family members?', + answer: + 'Yes, since this is a genetic test, it is possible that your results were passed down to you and your siblings from your parents and you will also pass them down to your children.', + ), + TextAnswerQuestion( + question: 'Who can I share my results with?', + answer: + 'We recommend that you share your results with your pharmacists, doctors, and close family members such as parents, siblings, and children.', + ), ], 'PharMe App': [ TextAnswerQuestion( diff --git a/app/lib/l10n/app_en.arb b/app/lib/l10n/app_en.arb index ffbc7af5..3d53b695 100644 --- a/app/lib/l10n/app_en.arb +++ b/app/lib/l10n/app_en.arb @@ -44,7 +44,7 @@ "err_generic": "Error", "update_warning_title": "Updated guidelines", - "update_warning_body": "The guidelines for gene-drug interactions were updated. Please review your information, especially for medications you are currently taking.", + "update_warning_body": "The guidelines for gene-drug interactions were updated. Please review your information, especially for drugs you are currently taking.", "faq_contact_us": "Do you have unanswered questions or feedback? Contact us", @@ -90,7 +90,7 @@ } } }, - "drugs_page_disclaimer": "Please note the information shown on this page is ONLY based on your DNA and relevant current medications. Other important factors like weight, age, pre-existing conditions, and drug interactions are not considered.", + "drugs_page_disclaimer": "Please note the information shown on this page is ONLY based on your DNA and relevant currently taken drugs. Other important factors like weight, age, pre-existing conditions, and drug interactions are not considered.", "drugs_page_is_inhibitor": "Taking {drugName} can influence your results for the following gene(s): {genes}", "@drugs_page_is_inhibitor": { "placeholders": { @@ -215,7 +215,9 @@ "drugs_page_implication_warfarin": "More information is needed to calculate your warfarin dose.", "drugs_page_recommendation_warfarin": "Consult your pharmacist or doctor for more information.", - "report_content_explanation": "Here is your PGx report. Tap on a gene name for more details on your results and a list of implicated drugs.", + "report_content_explanation": "This is your PGx test report. Tap on a gene name for more details on your results and a list of implicated drugs.", + "report_legend_text": "Next to your gene result the number of implicated drugs per guideline result is shown:", + "report_page_faq_tooltip": "To learn more about genetics in general, please refer to the FAQ", "report_page_indicator_explanation": "Phenotypes followed by an {indicatorName} ({indicator}) might be influenced by drugs you are currently taking", "@report_page_indicator_explanation": { "placeholders": { diff --git a/app/lib/report/pages/report.dart b/app/lib/report/pages/report.dart index e5910627..3a31030e 100644 --- a/app/lib/report/pages/report.dart +++ b/app/lib/report/pages/report.dart @@ -30,31 +30,30 @@ class ReportPage extends StatelessWidget { canPop: false, child: unscrollablePageScaffold( title: context.l10n.tab_report, + titleTooltip: context.l10n.report_page_faq_tooltip, body: Column( + crossAxisAlignment: CrossAxisAlignment.start, children: [ - PageDescription(Column(children: [ - PageDescriptionText(context.l10n.report_content_explanation), - SizedBox(height: PharMeTheme.smallSpace), - RichText(text: TextSpan( - text: context.l10n.genetic_information_text_part_1, - style: pageDescriptionTextStyle, - children: [ - linkTextSpan( - text: context.l10n.genetic_information_source, - onTap: openFurtherGeneticInformation, - ), - TextSpan( - text: context.l10n.genetic_information_text_part_2, - style: pageDescriptionTextStyle, - ), - ], - )), - ])), + PageDescription.fromText(context.l10n.report_content_explanation), scrollList( - userGenotypes.map((genotypeResult) => GeneCard( - genotypeResult, - key: Key('gene-card-${genotypeResult.key.value}') - )).toList(), + [ + PageDescription( + Column( + children: [ + PageDescriptionText(context.l10n.report_legend_text), + _buildWarningLevelIndicators( + getText: (warningLevel) => + warningLevel.getLabel(context), + separator: TextSpan(text: ', ') + ), + ] + ), + ), + ...userGenotypes.map((genotypeResult) => GeneCard( + genotypeResult, + key: Key('gene-card-${genotypeResult.key.value}') + )), + ], ), if (hasActiveInhibitors) PageIndicatorExplanation( context.l10n.report_page_indicator_explanation( @@ -67,7 +66,6 @@ class ReportPage extends StatelessWidget { ), ); } - } class GeneCard extends StatelessWidget { @@ -87,31 +85,6 @@ class GeneCard extends StatelessWidget { final affectedDrugs = CachedDrugs.instance.drugs?.filter( (drug) => drug.guidelineGenotypes.contains(genotypeResult.key.value) ) ?? []; - final warningLevelIndicators = WarningLevel.values.map( - (warningLevel) { - final warningLevelCount = affectedDrugs.filter( - (drug) => drug.warningLevel == warningLevel - ).length; - return warningLevelCount > 0 - ? Row( - textDirection: TextDirection.ltr, - children: [ - Icon( - warningLevel.icon, - size: PharMeTheme.mediumSpace, - color: warningLevel.textColor, - ), - SizedBox(width: PharMeTheme.smallSpace * 0.4), - Text( - warningLevelCount.toString(), - style: TextStyle(color: warningLevel.textColor), - ), - SizedBox(width: PharMeTheme.smallSpace * 0.8), - ] - ) - : SizedBox.shrink(); - } - ).toList(); return RoundedCard( onTap: () => context.router.push( GeneRoute(genotypeResult: genotypeResult) @@ -136,7 +109,16 @@ class GeneCard extends StatelessWidget { overflow: TextOverflow.ellipsis, ), ), - Row(children: warningLevelIndicators), + _buildWarningLevelIndicators( + getText: (warningLevel) { + final warningLevelCount = affectedDrugs.filter( + (drug) => drug.warningLevel == warningLevel + ).length; + return warningLevelCount > 0 + ? warningLevelCount.toString() + : null; + }, + ), ], ), ], @@ -147,3 +129,60 @@ class GeneCard extends StatelessWidget { ); } } + +RichText _buildWarningLevelIndicators({ + required String? Function(WarningLevel) getText, + InlineSpan? separator, +}) { + var content = []; + for (final (index, warningLevel) in WarningLevel.values.indexed) { + final text = getText(warningLevel); + if (text.isNullOrEmpty) continue; + final warningLevelIndicator = _buildWarningLevelIndicator( + warningLevel, + text: text!, + ); + final isLastItem = index == WarningLevel.values.length - 1; + content = isLastItem + ? [ ...content, ...warningLevelIndicator ] + : [ + ...content, + ...warningLevelIndicator, + separator ?? WidgetSpan( + child: SizedBox(width: PharMeTheme.smallSpace * 0.8), + ), + ]; + } + return RichText( + text: TextSpan( + style: PharMeTheme.textTheme.bodyMedium, + children: content, + ) + ); +} + +List _buildWarningLevelIndicator( + WarningLevel warningLevel, + { + required String text, + Widget? separator, + } +) { + return [ + WidgetSpan( + child: Icon( + warningLevel.icon, + color: warningLevel.textColor, + size: pageDescriptionTextStyle!.fontSize, + ), + ), + WidgetSpan( + child: separator ?? + SizedBox(width: PharMeTheme.smallSpace * 0.4), + ), + TextSpan( + text: text, + style: pageDescriptionTextStyle!.copyWith(color: warningLevel.textColor) + ), + ]; +} diff --git a/app/pubspec.yaml b/app/pubspec.yaml index ddb61cfa..1488382c 100644 --- a/app/pubspec.yaml +++ b/app/pubspec.yaml @@ -4,7 +4,7 @@ publish_to: 'none' version: 1.0.1+8 environment: - sdk: '>=2.17.0 <3.3.0' + sdk: '>=3.0.0 <3.3.0' flutter: '>=3.3.0' dependencies: