Skip to content

Commit

Permalink
feat(app): add state to filter chips
Browse files Browse the repository at this point in the history
  • Loading branch information
tamslo committed Sep 18, 2024
1 parent dc6e6cf commit e64c4d1
Show file tree
Hide file tree
Showing 3 changed files with 114 additions and 100 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ List<Widget> buildDrugCards(
key: Key('${keyPrefix}drug-card-${drug.name}'),
onTap: () => context.router
.push(DrugRoute(drug: drug))
// ignore: use_build_context_synchronously
.then((_) => context.read<DrugListCubit>().search()),
drug: drug,
showDrugInteractionIndicator: showDrugInteractionIndicator,
Expand Down
212 changes: 112 additions & 100 deletions app/lib/common/widgets/drug_search/drug_filters.dart
Original file line number Diff line number Diff line change
@@ -1,27 +1,110 @@
import 'package:popover/popover.dart';
import '../../module.dart';

class _FilterChip extends StatelessWidget {
const _FilterChip({
required this.onPressed,
required this.label,
required this.color,
required this.borderColor,
class _WarningLevelFilterChip extends HookWidget {
const _WarningLevelFilterChip({
required this.warningLevel,
required this.cubit,
required this.filter,
required this.drugs,
required this.activeDrugs,
required this.searchForDrugClass,
});

final void Function()? onPressed;
final Widget label;
final Color color;
final Color borderColor;
final WarningLevel warningLevel;
final DrugListCubit cubit;
final FilterState filter;
final List<Drug> drugs;
final ActiveDrugs activeDrugs;
final bool searchForDrugClass;

int _getFilteredNumber({
required FilterState itemFilter,
required List<Drug> drugs,
}) {
return itemFilter
.filter(drugs, activeDrugs, searchForDrugClass: searchForDrugClass)
.length;
}

bool _filterIsEnabled({
required FilterState itemFilter,
required List<Drug> drugs,
}) => _getFilteredNumber(itemFilter: itemFilter, drugs: drugs) > 0;

Widget _getFilterText(
BuildContext context,
WarningLevel warningLevel, {
required FilterState itemFilter,
required List<Drug> drugs,
bool enabled = true,
}) {
final numberTextColor = darkenColor(PharMeTheme.onSurfaceText, -0.2);
final disabledTextColor = darkenColor(numberTextColor, -0.2);
return Text.rich(
TextSpan(children: [
WidgetSpan(
child: Icon(
enabled ? warningLevel.icon : warningLevel.outlinedIcon,
color: PharMeTheme.onSurfaceText,
size: PharMeTheme.textTheme.labelMedium!.fontSize,
)),
TextSpan(text: ' '),
TextSpan(
text: warningLevel.getLabel(context),
style: PharMeTheme.textTheme.labelSmall!.copyWith(
color: enabled
? PharMeTheme.textTheme.labelSmall!.color
: disabledTextColor,
),
),
TextSpan(
text: ' (${
_getFilteredNumber(itemFilter: itemFilter, drugs: drugs)
})',
style: PharMeTheme.textTheme.labelSmall!.copyWith(
color: enabled ? numberTextColor : disabledTextColor,
),
),
]),
);
}

FilterState _warningLevelFilter(WarningLevel warningLevel) {
final currentFilter = FilterState.from(filter);
currentFilter.showWarningLevel.forEach(
(currentWarningLevel, currentValue) =>
currentFilter.showWarningLevel[currentWarningLevel] =
currentWarningLevel == warningLevel);
return currentFilter;
}

@override
Widget build(BuildContext context) {
final selected = useState(filter.showWarningLevel[warningLevel]!);
final itemFilter = _warningLevelFilter(warningLevel);
final enabled = _filterIsEnabled(itemFilter: itemFilter, drugs: drugs);
return GestureDetector(
onTap: onPressed,
onTap: enabled
? () {
final newValue = !selected.value;
cubit.search(
showWarningLevel: {warningLevel: newValue},
);
// Need to additionally set state to update chip in popover
selected.value = newValue;
}
: null,
child: DecoratedBox(
decoration: BoxDecoration(
color: color,
border: Border.all(color: borderColor),
color: selected.value && enabled
? warningLevel.color
: Colors.transparent,
border: Border.all(
color: selected.value && enabled
? darkenColor(warningLevel.color, 0.05)
: PharMeTheme.onSurfaceColor,
),
borderRadius: BorderRadius.all(
Radius.circular(PharMeTheme.outerCardRadius)
),
Expand All @@ -31,7 +114,13 @@ class _FilterChip extends StatelessWidget {
horizontal: PharMeTheme.mediumSpace * 0.5,
vertical: PharMeTheme.mediumSpace * 0.4,
),
child: label,
child: _getFilterText(
context,
warningLevel,
itemFilter: itemFilter,
drugs: drugs,
enabled: selected.value && enabled,
),
),
),
);
Expand Down Expand Up @@ -87,96 +176,19 @@ class DrugFilters extends StatelessWidget {
);
}

int _getFilteredNumber({
required FilterState itemFilter,
required List<Drug> drugs,
}) {
return itemFilter
.filter(drugs, activeDrugs, searchForDrugClass: searchForDrugClass)
.length;
}

bool _filterIsEnabled({
required FilterState itemFilter,
required List<Drug> drugs,
}) => _getFilteredNumber(itemFilter: itemFilter, drugs: drugs) > 0;

Widget _getFilterText(
BuildContext context,
WarningLevel warningLevel, {
required FilterState itemFilter,
required List<Drug> drugs,
bool enabled = true,
bool showText = true,
}) {
final numberTextColor = darkenColor(PharMeTheme.onSurfaceText, -0.2);
final disabledTextColor = darkenColor(numberTextColor, -0.2);
return Text.rich(
TextSpan(children: [
WidgetSpan(
child: Icon(
enabled ? warningLevel.icon : warningLevel.outlinedIcon,
color: PharMeTheme.onSurfaceText,
size: PharMeTheme.textTheme.labelMedium!.fontSize,
)),
if (showText) ...[
TextSpan(text: ' '),
TextSpan(
text: warningLevel.getLabel(context),
style: PharMeTheme.textTheme.labelSmall!.copyWith(
color: enabled
? PharMeTheme.textTheme.labelSmall!.color
: disabledTextColor,
),
),
],
TextSpan(
text: ' (${
_getFilteredNumber(itemFilter: itemFilter, drugs: drugs)
})',
style: PharMeTheme.textTheme.labelSmall!.copyWith(
color: enabled ? numberTextColor : disabledTextColor,
),
),
]),
);
}

List<Widget> _buildWarningLevelFilters(
BuildContext context,
List<Drug> drugs,
FilterState filter,
) {
FilterState warningLevelFilter(WarningLevel warningLevel) {
final currentFilter = FilterState.from(filter);
currentFilter.showWarningLevel.forEach(
(currentWarningLevel, currentValue) =>
currentFilter.showWarningLevel[currentWarningLevel] =
currentWarningLevel == warningLevel);
return currentFilter;
}
Widget buildWarningLevelItem(WarningLevel warningLevel) {
final value = filter.showWarningLevel[warningLevel]!;
final itemFilter = warningLevelFilter(warningLevel);
final enabled = _filterIsEnabled(itemFilter: itemFilter, drugs: drugs);
return _FilterChip(
onPressed: enabled ? () => cubit.search(
showWarningLevel: {warningLevel: !value},
) : null,
label: _getFilterText(
context,
warningLevel,
itemFilter: itemFilter,
drugs: drugs,
enabled: value && enabled,
showText: false,
),
color: value && enabled ? warningLevel.color : Colors.transparent,
borderColor: value && enabled
? darkenColor(warningLevel.color, 0.05)
: PharMeTheme.onSurfaceColor,
Widget buildWarningLevelItem(WarningLevel warningLevel) =>
_WarningLevelFilterChip(
warningLevel: warningLevel,
cubit: cubit,
drugs: drugs,
filter: filter,
activeDrugs: activeDrugs,
searchForDrugClass: searchForDrugClass,
);
}
return WarningLevel.values.map(buildWarningLevelItem).toList();
}

Expand Down Expand Up @@ -227,7 +239,7 @@ class DrugFilters extends StatelessWidget {
text: context.l10n.search_page_filter_label,
useLine: false,
),
..._buildWarningLevelFilters(context, allDrugs, filter),
..._buildWarningLevelFilters(allDrugs, filter),
],
),
),
Expand Down
1 change: 1 addition & 0 deletions app/lib/faq/pages/faq.dart
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,7 @@ class FaqPage extends StatelessWidget {
if (keyContext != null) {
Future.delayed(Duration(milliseconds: 200)).then((value) {
Scrollable.ensureVisible(
// ignore: use_build_context_synchronously
keyContext,
duration: Duration(milliseconds: 200),
alignmentPolicy: ScrollPositionAlignmentPolicy.keepVisibleAtEnd,
Expand Down

0 comments on commit e64c4d1

Please sign in to comment.