Skip to content

Commit

Permalink
feat(app): adapt inhibitor texts
Browse files Browse the repository at this point in the history
  • Loading branch information
tamslo committed Dec 28, 2023
1 parent 99a5ab6 commit 1420d8a
Show file tree
Hide file tree
Showing 21 changed files with 206 additions and 179 deletions.
17 changes: 17 additions & 0 deletions app/CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -132,3 +132,20 @@ needs to be adapted (see
[[IntegrationTestPlugin instance] setupChannels:registrar.messenger];
}
```

## Adapting test data

If you would like to test with specific test data but you don't have a user with
suitable data available, adapt the code in `utilities/genome_data.dart` as
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',
);
```
22 changes: 16 additions & 6 deletions app/lib/common/models/drug/drug_inhibitors.dart
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,7 @@

// structure: gene symbol -> drug name -> overwriting lookupkey

import 'package:dartx/dartx.dart';

import 'drug.dart';
import '../../module.dart';

// Inhibit phenotype for gene by overwriting with poor metabolizer
const Map<String, Map<String, String>> strongDrugInhibitors = {
Expand Down Expand Up @@ -63,9 +61,16 @@ bool isModerateInhibitor(String drugName) {
}

bool isInhibitor(String drugName) {
final influencingDrugs = _drugInhibitorsPerGene.keys.flatMap(
(gene) => _drugInhibitorsPerGene[gene]!);
return influencingDrugs.contains(drugName);
var drugIsInhibitor = false;
for (final geneSymbol in _drugInhibitorsPerGene.keys) {
final influencingDrugs = _drugInhibitorsPerGene[geneSymbol];
final originalLookup = UserData.lookupFor(geneSymbol, drug: drugName, useOverwrite: false);
if (influencingDrugs!.contains(drugName) && originalLookup != '0.0') {
drugIsInhibitor = true;
break;
}
}
return drugIsInhibitor;
}

List<String> inhibitedGenes(Drug drug) {
Expand All @@ -77,3 +82,8 @@ List<String> inhibitedGenes(Drug drug) {
List<String> inhibitorsFor(String geneSymbol) {
return _drugInhibitorsPerGene[geneSymbol] ?? [];
}

bool canBeInhibited(CpicPhenotype phenotype) {
return inhibitableGenes.contains(phenotype.geneSymbol) &&
phenotype.lookupkey != '0.0';
}
66 changes: 30 additions & 36 deletions app/lib/common/models/userdata/userdata.dart
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,12 @@ class PhenotypeInformation {
PhenotypeInformation({
required this.phenotype,
this.adaptionText,
this.overwrittenPhenotype,
this.overwrittenPhenotypeText,
});

String phenotype;
String? adaptionText;
String? overwrittenPhenotype;
String? overwrittenPhenotypeText;
}

/// UserData is a singleton data-class which contains various user-specific
Expand Down Expand Up @@ -48,14 +48,21 @@ class UserData {
@HiveField(0)
Map<String, Diplotype>? diplotypes;

static PhenotypeInformation phenotypeFor(
static PhenotypeInformation phenotypeInformationFor(
String gene,
BuildContext context,
{
String? drug,
String userSalutation = 'you',
bool thirdPerson = false,
bool useLongPrefix = false,
}
) {
final userSalutation = thirdPerson
? context.l10n.drugs_page_inhibitor_third_person_salutation
: context.l10n.drugs_page_inhibitor_direct_salutation;
final strongInhibitorTextPrefix = useLongPrefix
? context.l10n.strong_inhibitor_long_prefix
: context.l10n.gene_page_phenotype.toLowerCase();
final originalPhenotype = UserData.instance.diplotypes?[gene]?.phenotype;
if (originalPhenotype == null) {
return PhenotypeInformation(
Expand All @@ -66,32 +73,19 @@ class UserData {
if (activeInhibitors.isEmpty) {
return PhenotypeInformation(phenotype: originalPhenotype);
}
final overwrittenLookup = UserData.overwrittenLookup(gene, drug: drug);
if (overwrittenLookup == null) {
return PhenotypeInformation(
phenotype: originalPhenotype,
adaptionText: context.l10n.drugs_page_moderate_inhibitors(
userSalutation,
enumerationWithAnd(
activeInhibitors,
context
),
),
);
}
final activeStrongInhibitors = activeInhibitors.filter(
isStrongInhibitor
).toList();
final activeModerateInhibitors = activeInhibitors.filter(
isModerateInhibitor
).toList();
final overwritePhenotype = context.l10n.general_poor_metabolizer;
final currentPhenotypeEqualsOverwritePhenotype =
originalPhenotype.toLowerCase() == overwritePhenotype.toLowerCase();
if (currentPhenotypeEqualsOverwritePhenotype) {
return PhenotypeInformation(
phenotype: originalPhenotype,
adaptionText: context.l10n.drugs_page_inhibitors_poor_metabolizer(
);
}
final overwrittenLookup = UserData.overwrittenLookup(gene, drug: drug);
if (overwrittenLookup == null) {
return PhenotypeInformation(
phenotype: originalPhenotype,
adaptionText: context.l10n.drugs_page_moderate_inhibitors(
userSalutation,
enumerationWithAnd(
activeInhibitors,
Expand All @@ -100,20 +94,20 @@ class UserData {
),
);
}
final adaptionText = activeModerateInhibitors.isEmpty
? context.l10n.drugs_page_strong_inhibitors(
userSalutation,
enumerationWithAnd(activeStrongInhibitors, context),
)
: context.l10n.drugs_page_moderate_and_strong_inhibitors(
userSalutation,
enumerationWithAnd(activeStrongInhibitors, context),
enumerationWithAnd(activeModerateInhibitors, context),
);
final originalPhenotypeText = context.l10n.drugs_page_original_phenotype(
thirdPerson
? context.l10n.drugs_page_inhibitor_third_person_salutation_genitive
: context.l10n.drugs_page_inhibitor_direct_salutation_genitive,
originalPhenotype,
);
return PhenotypeInformation(
phenotype: overwritePhenotype,
adaptionText: adaptionText,
overwrittenPhenotype: originalPhenotype,
adaptionText: context.l10n.drugs_page_strong_inhibitors(
strongInhibitorTextPrefix,
userSalutation,
enumerationWithAnd(activeInhibitors, context),
),
overwrittenPhenotypeText: originalPhenotypeText,
);
}

Expand Down
11 changes: 5 additions & 6 deletions app/lib/common/utilities/pdf_utils.dart
Original file line number Diff line number Diff line change
Expand Up @@ -125,22 +125,21 @@ List<pw.Widget> _buildDrugPart(Drug drug, BuildContext buildContext) {
}

String? _getPhenotypeInfo(String gene, Drug drug, BuildContext context) {
final phenotypeInformation = UserData.phenotypeFor(
final phenotypeInformation = UserData.phenotypeInformationFor(
gene,
context,
drug: drug.name,
userSalutation: context.l10n.general_the_user,
thirdPerson: true,
useLongPrefix: true,
);
if (phenotypeInformation.adaptionText.isNullOrBlank) {
return phenotypeInformation.phenotype;
}
var phenotypeInformationText = '${phenotypeInformation.phenotype} ('
'${phenotypeInformation.adaptionText}';
if (phenotypeInformation.overwrittenPhenotype.isNotNullOrBlank) {
if (phenotypeInformation.overwrittenPhenotypeText.isNotNullOrBlank) {
phenotypeInformationText = '$phenotypeInformationText; '
'${context.l10n.drugs_page_original_phenotype(
phenotypeInformation.overwrittenPhenotype!
)}';
'${phenotypeInformation.overwrittenPhenotypeText!}';
}
return '$phenotypeInformationText)';
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import '../../../common/module.dart';
import '../module.dart';

class TableRowDefinition {
const TableRowDefinition(this.key, this.value);
Expand All @@ -10,6 +10,7 @@ Table buildTable(
List<TableRowDefinition> rowDefinitions,
{
TextStyle? style,
bool boldHeader = true,
}
) {
return Table(
Expand All @@ -18,6 +19,7 @@ Table buildTable(
rowDefinition.key,
rowDefinition.value,
style ?? PharMeTheme.textTheme.bodyMedium!,
boldHeader: boldHeader,
)).toList(),
);
}
Expand All @@ -26,14 +28,17 @@ TableRow _buildRow(
String key,
String value,
TextStyle textStyle,
{ required bool boldHeader }
) {
return TableRow(
children: [
Padding(
padding: EdgeInsets.only(right: PharMeTheme.smallSpace),
child: Text(
key,
style: textStyle.copyWith(fontWeight: FontWeight.bold),
style: boldHeader
? textStyle.copyWith(fontWeight: FontWeight.bold)
: textStyle,
),
),
Text(value, style: textStyle),
Expand Down
43 changes: 35 additions & 8 deletions app/lib/common/widgets/drug_search.dart
Original file line number Diff line number Diff line change
Expand Up @@ -64,14 +64,6 @@ class DrugSearch extends HookWidget {
if (showFilter) buildFilter(context),
]
),
SizedBox(height: PharMeTheme.smallSpace),
if (showDrugInteractionIndicator)
PageIndicatorExplanation(
context.l10n.search_page_indicator_explanation(
drugInteractionIndicatorName,
drugInteractionIndicator
),
),
scrollList(
keepPosition: keepPosition,
buildDrugList(
Expand All @@ -86,6 +78,18 @@ class DrugSearch extends HookWidget {
useDrugClass: useDrugClass,
)
),
state.when(
initial: SizedBox.shrink,
loading: SizedBox.shrink,
loaded: (allDrugs, filter) =>
maybeBuildInteractionIndicator(
context,
activeDrugs,
allDrugs,
filter,
),
error: SizedBox.shrink,
)
],
);
}
Expand Down Expand Up @@ -132,4 +136,27 @@ class DrugSearch extends HookWidget {
iconData: Icons.filter_list_rounded,
);
}
Widget maybeBuildInteractionIndicator(
BuildContext context,
ActiveDrugs activeDrugs,
List<Drug> drugs,
FilterState filter,
) {
if (showDrugInteractionIndicator) {
final filteredDrugs = filter.filter(
drugs,
activeDrugs,
useDrugClass: useDrugClass,
);
if (filteredDrugs.any((drug) => isInhibitor(drug.name))) {
return PageIndicatorExplanation(
context.l10n.search_page_indicator_explanation(
drugInteractionIndicatorName,
drugInteractionIndicator
),
);
}
}
return SizedBox.shrink();
}
}
5 changes: 5 additions & 0 deletions app/lib/common/widgets/error_handler.dart
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import 'package:flutter/foundation.dart';

import '../module.dart';

class ErrorHandler extends StatefulWidget {
Expand Down Expand Up @@ -34,6 +36,9 @@ class ErrorHandlerState extends State<ErrorHandler> {
}) async {
debugPrint(exception.toString());
debugPrintStack(stackTrace: stackTrace);
if (kDebugMode) {
if (exception is AssertionError) return;
}
final errorString = exception.toString();
if (_needToHandleError(exception)) {
final errorMailInfo = stackTrace != null
Expand Down
1 change: 1 addition & 0 deletions app/lib/common/widgets/module.dart
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
export 'annotation_table.dart';
export 'checkbox_list_tile_wrapper.dart';
export 'checkbox_wrapper.dart';
export 'dialog_action.dart';
Expand Down
6 changes: 1 addition & 5 deletions app/lib/common/widgets/page_indicator_explanation.dart
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,7 @@ class PageIndicatorExplanation extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Padding(
padding: EdgeInsets.only(
left: PharMeTheme.smallSpace,
right: PharMeTheme.smallSpace,
bottom: PharMeTheme.smallSpace,
),
padding: EdgeInsets.all(PharMeTheme.smallSpace),
child: Text(text),
);
}
Expand Down
6 changes: 5 additions & 1 deletion app/lib/common/widgets/page_scaffold.dart
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,11 @@ Scaffold unscrollablePageScaffold({
appBar: appBar,
body: SafeArea(
child: Padding(
padding: EdgeInsets.all(padding ?? PharMeTheme.smallSpace),
padding: EdgeInsets.only(
left: padding ?? PharMeTheme.smallSpace,
top: padding ?? PharMeTheme.smallSpace,
right: padding ?? PharMeTheme.smallSpace,
),
child: body,
),
),
Expand Down
21 changes: 2 additions & 19 deletions app/lib/common/widgets/scroll_list.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,7 @@ import 'package:flutter_list_view/flutter_list_view.dart';

import '../module.dart';

Widget scrollList(List<Widget> body, {
bool keepPosition = false,
double? verticalPadding,
}) {
Widget scrollList(List<Widget> body, { bool keepPosition = false }) {
String getItemKey(Widget widget) => widget.key.toString();
if (body.map(getItemKey).toSet().length != body.length) {
throw Exception('Items passed to scrollList need unique keys');
Expand All @@ -18,21 +15,7 @@ Widget scrollList(List<Widget> body, {
padding: EdgeInsets.only(right: PharMeTheme.mediumSpace),
child: FlutterListView(
delegate: FlutterListViewDelegate(
(context, index) => (index == 0)
? Padding(
padding: EdgeInsets.only(
top: verticalPadding ?? PharMeTheme.smallSpace,
),
child: body[index]
)
: (index == body.length - 1)
? Padding(
padding: EdgeInsets.only(
bottom: verticalPadding ?? PharMeTheme.smallSpace,
),
child: body[index]
)
: body[index],
(context, index) => body[index],
childCount: body.length,
onItemKey: (index) => getItemKey(body[index]),
keepPosition: keepPosition,
Expand Down
4 changes: 3 additions & 1 deletion app/lib/drug/pages/drug.dart
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,9 @@ class DrugPage extends StatelessWidget {

Widget _buildDrugsPage(BuildContext context, { required bool loading }) {
return pageScaffold(
title: drug.name.capitalize(),
title: isInhibitor(drug.name)
? '${drug.name.capitalize()}$drugInteractionIndicator'
: drug.name.capitalize(),
actions: [
IconButton(
onPressed: loading ? null : () =>
Expand Down
Loading

0 comments on commit 1420d8a

Please sign in to comment.