From b1c50c21e723c6193a252f01662b19cc3d8c0726 Mon Sep 17 00:00:00 2001 From: Tamara Slosarek Date: Fri, 29 Dec 2023 01:21:55 +0100 Subject: [PATCH] feat(#669): add custom Warfarin content --- app/CONTRIBUTING.md | 52 ++++++- app/lib/drug/pages/drug.dart | 22 +-- .../drug/widgets/annotation_cards/drug.dart | 4 +- .../widgets/annotation_cards/guideline.dart | 132 ++++++++++++++---- app/lib/l10n/app_en.arb | 4 + 5 files changed, 158 insertions(+), 56 deletions(-) diff --git a/app/CONTRIBUTING.md b/app/CONTRIBUTING.md index 239dfb14..336b2475 100644 --- a/app/CONTRIBUTING.md +++ b/app/CONTRIBUTING.md @@ -141,11 +141,49 @@ shown below. ```dart // TODO(after-testing): remove test data adaption -UserData.instance.diplotypes!['CYP2D6'] = Diplotype( - gene: 'CYP2D6', - resultType: 'Diplotype', - genotype: '*18/*143', - phenotype: 'Poor Metabolizer', - allelesTested: '*xN.*3.*4.*5.*6.*8.*9.*10.*14A.*14B.*17.*18.*41.*143', -); + UserData.instance.diplotypes!['CYP2D6'] = Diplotype( + gene: 'CYP2D6', + resultType: 'Diplotype', + genotype: '*18/*143', + phenotype: 'Poor Metabolizer', + allelesTested: '', + ); +``` + +You can use the CPIC API to get reasonable genotype-phenotype pairings, e.g., +with +`https://api.cpicpgx.org/v1/diplotype?genesymbol=eq.CYP2C9&select=genesymbol,diplotype,generesult`. + +Some more examples are collected below (this is for testing what is shown for +Warfarin): + +```dart + UserData.instance.diplotypes!['CYP2C9'] = Diplotype( + gene: 'CYP2C9', + resultType: 'Diplotype', + genotype: '*11/*13', + phenotype: 'Poor Metabolizer', + allelesTested: '', + ); + UserData.instance.diplotypes!['VKORC1'] = Diplotype( + gene: 'VKORC1', + resultType: 'Diplotype', + genotype: '-1639G>A variant carriers', + phenotype: '-1639G>A variant carriers', + allelesTested: '', + ); + UserData.instance.diplotypes!['CYP4F2'] = Diplotype( + gene: 'CYP4F2', + resultType: 'Diplotype', + genotype: 'rs2108622 T carriers', + phenotype: 'rs2108622 T carriers', + allelesTested: '', + ); + UserData.instance.diplotypes!['CYP2C'] = Diplotype( + gene: 'CYP2C', + resultType: 'Diplotype', + genotype: 'rs12777823 A carriers', + phenotype: 'rs12777823 A carriers', + allelesTested: '', + ); ``` diff --git a/app/lib/drug/pages/drug.dart b/app/lib/drug/pages/drug.dart index 4e83e6d3..4fe7f0c0 100644 --- a/app/lib/drug/pages/drug.dart +++ b/app/lib/drug/pages/drug.dart @@ -52,7 +52,7 @@ class DrugPage extends StatelessWidget { child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - DrugAnnotationCard( + DrugAnnotationCards( drug, isActive: drug.isActive, setActivity: ({ value }) => @@ -60,11 +60,6 @@ class DrugPage extends StatelessWidget { disabled: loading, ), SizedBox(height: PharMeTheme.mediumSpace), - SubHeader( - context.l10n.drugs_page_header_guideline, - tooltip: _buildGuidelineTooltipText(context), - ), - SizedBox(height: PharMeTheme.smallSpace), GuidelineAnnotationCard(drug), ], ), @@ -72,19 +67,4 @@ class DrugPage extends StatelessWidget { ], ); } - - String _buildGuidelineTooltipText(BuildContext context) { - return drug.userGuideline != null - ? context.l10n.drugs_page_tooltip_guideline( - drug.userGuideline!.externalData.first.source - ) - : drug.userOrFirstGuideline != null - // Guideline for drug is present but not for genotype - ? context.l10n.drugs_page_tooltip_missing_guideline_for_drug_or_genotype( - context.l10n.drugs_page_tooltip_missing_genotype - ) - : context.l10n.drugs_page_tooltip_missing_guideline_for_drug_or_genotype( - context.l10n.drugs_page_tooltip_missing_drug - ); - } } diff --git a/app/lib/drug/widgets/annotation_cards/drug.dart b/app/lib/drug/widgets/annotation_cards/drug.dart index a8307ea6..2cc58441 100644 --- a/app/lib/drug/widgets/annotation_cards/drug.dart +++ b/app/lib/drug/widgets/annotation_cards/drug.dart @@ -1,8 +1,8 @@ import '../../../common/module.dart'; import '../sub_header.dart'; -class DrugAnnotationCard extends StatelessWidget { - const DrugAnnotationCard( +class DrugAnnotationCards extends StatelessWidget { + const DrugAnnotationCards( this.drug, { required this.isActive, required this.setActivity, diff --git a/app/lib/drug/widgets/annotation_cards/guideline.dart b/app/lib/drug/widgets/annotation_cards/guideline.dart index e6f8ce9b..32839d61 100644 --- a/app/lib/drug/widgets/annotation_cards/guideline.dart +++ b/app/lib/drug/widgets/annotation_cards/guideline.dart @@ -3,6 +3,25 @@ import 'package:url_launcher/url_launcher.dart'; import '../../../common/module.dart'; import '../module.dart'; +enum WarfarinContent { + tooltip, + implication, + recommendation, + color, + icon, +} + +final warfarinProperties = { + WarfarinContent.tooltip: (context) => + context.l10n.drugs_page_tooltip_warfarin, + WarfarinContent.implication: (context) => + context.l10n.drugs_page_implication_warfarin, + WarfarinContent.recommendation: (context) => + context.l10n.drugs_page_recommendation_warfarin, + WarfarinContent.color: (_) => WarningLevel.none.color, + WarfarinContent.icon: (_) => WarningLevel.none.icon, +}; + class GuidelineAnnotationCard extends StatelessWidget { const GuidelineAnnotationCard(this.drug); @@ -10,46 +29,86 @@ class GuidelineAnnotationCard extends StatelessWidget { @override Widget build(BuildContext context) { - return RoundedCard( - innerPadding: const EdgeInsets.all(PharMeTheme.mediumSpace), - child: SingleChildScrollView( - child: Column(crossAxisAlignment: CrossAxisAlignment.start, children: [ - if (drug.guidelines.isNotEmpty) ...[ - _buildHeader(context), - SizedBox(height: PharMeTheme.mediumSpace), - _buildCard(context), - SizedBox(height: PharMeTheme.mediumSpace), - _buildSourcesSection(context), - ] - else ...[ - _buildHeader(context), - SizedBox(height: PharMeTheme.smallSpace), - _buildCard(context), - ], - ]), - ), + return Column( + children: [ + SubHeader( + context.l10n.drugs_page_header_guideline, + tooltip: _buildGuidelineTooltipText(context), + ), + SizedBox(height: PharMeTheme.smallSpace), + RoundedCard( + innerPadding: const EdgeInsets.all(PharMeTheme.mediumSpace), + child: SingleChildScrollView( + child: Column(crossAxisAlignment: CrossAxisAlignment.start, children: [ + if (drug.guidelines.isNotEmpty) ...[ + _buildHeader(context), + SizedBox(height: PharMeTheme.mediumSpace), + _buildCard(context), + SizedBox(height: PharMeTheme.mediumSpace), + _buildSourcesSection(context), + ] + else ...[ + _buildHeader(context), + SizedBox(height: PharMeTheme.smallSpace), + _buildCard(context), + ], + ]), + ), + ), + ], ); } + dynamic actualOrWarfarinContent(String drugName, BuildContext context, { + required dynamic actual, + required WarfarinContent content, + }) { + if (drugName.toLowerCase() == 'warfarin') { + final getWarfarinContent = warfarinProperties[content]!; + return getWarfarinContent(context); + } + return actual; + } + Widget _buildCard(BuildContext context) { - final upperCardText = drug.userGuideline?.annotations.implication ?? - context.l10n.drugs_page_no_guidelines_for_phenotype_implication( - drug.name - ); - final lowerCardText = drug.userGuideline?.annotations.recommendation ?? - context.l10n.drugs_page_no_guidelines_for_phenotype_recommendation; + final upperCardText = actualOrWarfarinContent( + drug.name, + context, + actual: drug.userGuideline?.annotations.implication ?? + context.l10n.drugs_page_no_guidelines_for_phenotype_implication( + drug.name + ), + content: WarfarinContent.implication, + ); + final lowerCardText = actualOrWarfarinContent( + drug.name, + context, + actual: drug.userGuideline?.annotations.recommendation ?? + context.l10n.drugs_page_no_guidelines_for_phenotype_recommendation, + content: WarfarinContent.recommendation, + ); return RoundedCard( key: Key('annotationCard'), radius: PharMeTheme.innerCardRadius, outerHorizontalPadding: 0, outerVerticalPadding: 0, - color: drug.warningLevel.color, + color: actualOrWarfarinContent( + drug.name, + context, + actual: drug.warningLevel.color, + content: WarfarinContent.color + ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Row(children: [ Icon( - drug.warningLevel.icon, + actualOrWarfarinContent( + drug.name, + context, + actual: drug.warningLevel.icon, + content: WarfarinContent.icon + ), color: PharMeTheme.onSurfaceText, size: PharMeTheme.largeSpace, ), @@ -75,6 +134,27 @@ class GuidelineAnnotationCard extends StatelessWidget { ); } + String _buildGuidelineTooltipText(BuildContext context) { + final actualTooltip = drug.userGuideline != null + ? context.l10n.drugs_page_tooltip_guideline( + drug.userGuideline!.externalData.first.source + ) + : drug.userOrFirstGuideline != null + // Guideline for drug is present but not for genotype + ? context.l10n.drugs_page_tooltip_missing_guideline_for_drug_or_genotype( + context.l10n.drugs_page_tooltip_missing_genotype + ) + : context.l10n.drugs_page_tooltip_missing_guideline_for_drug_or_genotype( + context.l10n.drugs_page_tooltip_missing_drug + ); + return actualOrWarfarinContent( + drug.name, + context, + actual: actualTooltip, + content: WarfarinContent.tooltip, + ); + } + Widget _buildHeader(BuildContext context) { if (drug.userGuideline == null && drug.guidelines.isEmpty) { return Text( diff --git a/app/lib/l10n/app_en.arb b/app/lib/l10n/app_en.arb index fe19c080..74669a96 100644 --- a/app/lib/l10n/app_en.arb +++ b/app/lib/l10n/app_en.arb @@ -201,6 +201,10 @@ } }, + "drugs_page_tooltip_warfarin": "CPIC guidelines provide recommendations on which drugs to use based on your DNA. However, to calculate your warfarin dose, more information is needed.", + "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_page_indicator_explanation": "Phenotypes followed by an {indicatorName} ({indicator}) might be influenced by drugs you are currently taking", "@report_page_indicator_explanation": {