Skip to content

Commit

Permalink
feat(#691): add numbers behind filter menu items
Browse files Browse the repository at this point in the history
* Moves withFilterData up to fix that cubit is closed when closing
  the drawer
* Refactors check whether to get lookups for better debugging
  • Loading branch information
tamslo committed Feb 22, 2024
1 parent aa4ce48 commit 118e239
Show file tree
Hide file tree
Showing 7 changed files with 198 additions and 137 deletions.
11 changes: 4 additions & 7 deletions app/lib/common/utilities/genome_data.dart
Original file line number Diff line number Diff line change
Expand Up @@ -73,16 +73,13 @@ Future<void> updateGenotypeResults() async {
bool shouldUpdateGenotypeResults() {
final genotypeResultsPresent =
UserData.instance.labData?.isNotEmpty ?? false;
final lookupsAreOutdated = MetaData.instance.lookupsLastFetchDate == null ||
DateTime.now().difference(MetaData.instance.lookupsLastFetchDate!) >
cpicMaxCacheTime;
final labDataPresent = UserData.instance.labData?.isNotEmpty ?? false;
return (!genotypeResultsPresent || _isOutDated()) && labDataPresent;
return labDataPresent && (!genotypeResultsPresent || lookupsAreOutdated);
}

bool shouldFetchDiplotypes() {
return UserData.instance.labData == null;
}

bool _isOutDated() {
final lastFetchDate = MetaData.instance.lookupsLastFetchDate;
if (lastFetchDate == null) return true;
return DateTime.now().difference(lastFetchDate) > cpicMaxCacheTime;
}
96 changes: 45 additions & 51 deletions app/lib/common/widgets/drug_search/builder.dart
Original file line number Diff line number Diff line change
@@ -1,21 +1,22 @@

import 'package:flutter/cupertino.dart';
import 'package:provider/provider.dart';

import '../../../../common/module.dart';
import '../../../drug/widgets/tooltip_icon.dart';

class DrugSearch extends HookWidget {
DrugSearch({
const DrugSearch({
super.key,
required this.showFilter,
required this.buildDrugItems,
required this.showDrugInteractionIndicator,
this.useDrugClass = true,
required this.useDrugClass,
required this.cubit,
required this.state,
required this.activeDrugs,
this.keepPosition = false,
this.drugItemsBuildParams,
DrugListCubit? cubit,
}) : cubit = cubit ?? DrugListCubit();
});

final bool showFilter;
final bool useDrugClass;
Expand All @@ -30,57 +31,50 @@ class DrugSearch extends HookWidget {
) buildDrugItems;
final bool showDrugInteractionIndicator;
final DrugListCubit cubit;
final DrugListState state;
final ActiveDrugs activeDrugs;
final Map? drugItemsBuildParams;

@override
Widget build(BuildContext context) {
final searchController = useTextEditingController();
return Consumer<ActiveDrugs>(
builder: (context, activeDrugs, child) => BlocProvider(
create: (context) => cubit,
child: BlocBuilder<DrugListCubit, DrugListState>(
builder: (context, state) {
return Column(
children: [
Padding(
padding: EdgeInsets.only(
left: PharMeTheme.smallSpace,
right: PharMeTheme.smallSpace,
bottom: PharMeTheme.smallSpace,
),
child: Row(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
..._buildSearchBarItems(context, searchController),
if (showFilter) FilterButton(),
],
),
),
scrollList(
keepPosition: keepPosition,
buildDrugList(
context,
state,
activeDrugs,
buildDrugItems: buildDrugItems,
noDrugsMessage: context.l10n.search_no_drugs(
showFilter
? context.l10n.search_no_drugs_with_filter_amendment
: ''
),
drugItemsBuildParams: drugItemsBuildParams,
showDrugInteractionIndicator:
showDrugInteractionIndicator,
useDrugClass: useDrugClass,
)
),
_maybeBuildInteractionIndicator(context, state, activeDrugs)
?? SizedBox.shrink(),
],
);
}
)
)
return Column(
children: [
Padding(
padding: EdgeInsets.only(
left: PharMeTheme.smallSpace,
right: PharMeTheme.smallSpace,
bottom: PharMeTheme.smallSpace,
),
child: Row(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
..._buildSearchBarItems(context, searchController),
if (showFilter) FilterButton(),
],
),
),
scrollList(
keepPosition: keepPosition,
buildDrugList(
context,
state,
activeDrugs,
buildDrugItems: buildDrugItems,
noDrugsMessage: context.l10n.search_no_drugs(
showFilter
? context.l10n.search_no_drugs_with_filter_amendment
: ''
),
drugItemsBuildParams: drugItemsBuildParams,
showDrugInteractionIndicator:
showDrugInteractionIndicator,
useDrugClass: useDrugClass,
)
),
_maybeBuildInteractionIndicator(context, state, activeDrugs)
?? SizedBox.shrink(),
],
);
}

Expand Down
20 changes: 20 additions & 0 deletions app/lib/common/widgets/drug_search/filter_data_wrapper.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import 'package:provider/provider.dart';

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

Widget withFilterData({
required DrugListCubit cubit,
required Widget Function(
BuildContext context,
DrugListCubit cubit,
DrugListState state,
ActiveDrugs activeDrugs,
) builder,
}) => Consumer<ActiveDrugs>(
builder: (context, activeDrugs, child) => BlocProvider(
create: (context) => cubit,
child: BlocBuilder<DrugListCubit, DrugListState>(
builder: (context, state) => builder(context, cubit, state, activeDrugs),
),
),
);
143 changes: 87 additions & 56 deletions app/lib/common/widgets/drug_search/filter_menu.dart
Original file line number Diff line number Diff line change
Expand Up @@ -29,73 +29,104 @@ class FilterMenuItem {
set value(newValue) => _value = newValue;
bool get value => _value;
}

class FilterMenu extends HookWidget {
const FilterMenu(this.cubit);
const FilterMenu(this.cubit, this.state, this.activeDrugs, {
required this.useDrugClass
});

final DrugListCubit cubit;
final DrugListState state;
final ActiveDrugs activeDrugs;
final bool useDrugClass;

@override
Widget build(BuildContext context) {
return SafeArea(
child: Column(
children: _menuItems.map(
(item) => PopupMenuItem(child: StatefulBuilder(
builder: (context, setState) {
return item.build(
context,
value: item.value,
statefulOnChange: ([_]) {
final newValue = !item.value;
setState(() => item.value = newValue);
item.updateSearch(newValue);
},
);
}),
),
).toList(),
),
return _buildFilters(context) ?? SizedBox.shrink();
}

Widget? _buildFilters(BuildContext context) {
return state.whenOrNull(loaded: (allDrugs, filter) =>
SafeArea(
child: Column(
children: _geMenuItems(context, allDrugs, filter, activeDrugs),
),
)
);
}

List<FilterMenuItem> get _menuItems => [
FilterMenuItem(
initialValue: cubit.filter?.showInactive ?? false,
updateSearch: (newValue) => cubit.search(showInactive: newValue),
build: (context, { required value, required statefulOnChange }) =>
DropdownButton<bool>(
value: value,
items: [
DropdownMenuItem<bool>(
value: true,
child: Text('${context.l10n.search_page_filter_all_drugs} '),
List<Widget> _geMenuItems(
BuildContext context,
List<Drug> drugs,
FilterState filter,
ActiveDrugs activeDrugs,
) {
String formatItemFilterNumber(FilterState itemFilter) =>
'(${
itemFilter.filter(drugs, activeDrugs, useDrugClass: useDrugClass).length
})';
String drugStatusNumber({ required bool showInactive}) =>
formatItemFilterNumber(FilterState.from(
FilterState.initial(),
showInactive: showInactive,
));
String warningLevelNumber(WarningLevel warningLevel) {
final currentWarningLevelFilter = FilterState.from(filter);
currentWarningLevelFilter.showWarningLevel.forEach(
(currentWarningLevel, currentValue) =>
currentWarningLevelFilter.showWarningLevel[currentWarningLevel] =
currentWarningLevel == warningLevel
);
return formatItemFilterNumber(currentWarningLevelFilter);
}
Widget buildDrugStatusItem() {
final value = filter.showInactive;
return DropdownButton<bool>(
value: value,
items: [
DropdownMenuItem<bool>(
value: true,
child: Text(
'${context.l10n.search_page_filter_all_drugs} '
'${drugStatusNumber(showInactive: true)}'
),
DropdownMenuItem<bool>(
value: false,
child: Text('${context.l10n.search_page_filter_only_active_drugs} '),
),
DropdownMenuItem<bool>(
value: false,
child: Text(
'${context.l10n.search_page_filter_only_active_drugs} '
'${drugStatusNumber(showInactive: false)}'
),
],
onChanged: (newValue) => statefulOnChange(newValue),
),
],
onChanged: (newValue) => newValue != value
? cubit.search(showInactive: newValue)
: null,
);
}
Widget buildWarningLevelItem(WarningLevel warningLevel) {
final value = filter.showWarningLevel[warningLevel]!;
return ActionChip(
onPressed: () => cubit.search(
showWarningLevel: { warningLevel: !value },
),
),
...WarningLevel.values
.filter((warningLevel) => warningLevel != WarningLevel.none)
.map((warningLevel) => FilterMenuItem(
initialValue: cubit.filter?.showWarningLevel[warningLevel] ?? false,
updateSearch: (newValue) => cubit.search(
showWarningLevel: { warningLevel: newValue },
avatar: Icon(
value ? warningLevel.icon : warningLevel.outlinedIcon,
color: value ? PharMeTheme.onSurfaceText : warningLevel.textColor,
),
build: (context, { required value, required statefulOnChange }) =>
ActionChip(
onPressed: () => statefulOnChange(!value),
avatar: Icon(
value ? warningLevel.icon : warningLevel.outlinedIcon,
color: value ? PharMeTheme.onSurfaceText : warningLevel.textColor,
),
label: Text('', style: TextStyle(color: PharMeTheme.onSurfaceText)),
visualDensity: VisualDensity.compact,
color: MaterialStatePropertyAll(value ? warningLevel.color : Colors.transparent),
),
)),
];
label: Text(warningLevelNumber(warningLevel),
style: TextStyle(color: PharMeTheme.onSurfaceText)),
visualDensity: VisualDensity.compact,
color: MaterialStatePropertyAll(value
? warningLevel.color
: Colors.transparent
),
);
}
return [
buildDrugStatusItem(),
...WarningLevel.values
.filter((warningLevel) => warningLevel != WarningLevel.none)
.map(buildWarningLevelItem),
];
}
}
1 change: 1 addition & 0 deletions app/lib/common/widgets/module.dart
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ export 'drug_list/builder.dart';
export 'drug_list/cubit.dart';
export 'drug_list/drug_items/drug_cards.dart';
export 'drug_search/builder.dart';
export 'drug_search/filter_data_wrapper.dart';
export 'drug_search/filter_menu.dart';
export 'error_handler.dart';
export 'full_width_button.dart';
Expand Down
32 changes: 19 additions & 13 deletions app/lib/drug_selection/pages/drug_selection.dart
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ class DrugSelectionPage extends HookWidget {
);
}
),
)
),
);
}

Expand Down Expand Up @@ -77,18 +77,24 @@ class DrugSelectionPage extends HookWidget {
],
);
}
return DrugSearch(
showFilter: false,
keepPosition: true,
useDrugClass: false,
buildDrugItems: buildDrugCheckboxList,
drugItemsBuildParams: {
'checkboxesEnabled': _isEditable(state),
'onCheckboxChange': (drug, value) => context
.read<DrugSelectionCubit>()
.updateDrugActivity(drug, value),
},
showDrugInteractionIndicator: false,
return withFilterData(
cubit: DrugListCubit(),
builder: (context, builderCubit, builderState, activeDrugs) => DrugSearch(
showFilter: false,
cubit: builderCubit,
state: builderState,
activeDrugs: activeDrugs,
keepPosition: true,
useDrugClass: false,
buildDrugItems: buildDrugCheckboxList,
drugItemsBuildParams: {
'checkboxesEnabled': _isEditable(state),
'onCheckboxChange': (drug, value) => context
.read<DrugSelectionCubit>()
.updateDrugActivity(drug, value),
},
showDrugInteractionIndicator: false,
),
);
}
}
Loading

0 comments on commit 118e239

Please sign in to comment.