Skip to content

Commit

Permalink
fix: Searchable dropdown filters
Browse files Browse the repository at this point in the history
  • Loading branch information
Gustl22 committed Apr 19, 2024
1 parent c9f2d4f commit edfd27c
Show file tree
Hide file tree
Showing 12 changed files with 136 additions and 150 deletions.
13 changes: 5 additions & 8 deletions wrestling_scoreboard_client/lib/view/screens/edit/bout_edit.dart
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ abstract class BoutEditState<T extends BoutEdit> extends ConsumerState<T> implem
deleteParticipantState: (participation) => _blueParticipation = null,
),
ListTile(
title: getDropdown<WeightClass>(
title: SearchableDropdown<WeightClass>(
icon: const Icon(Icons.fitness_center),
selectedItem: _weightClass,
label: AppLocalizations.of(context)!.weightClass,
Expand All @@ -84,12 +84,9 @@ abstract class BoutEditState<T extends BoutEdit> extends ConsumerState<T> implem
_weightClass = value;
}),
itemAsString: (u) => u.name,
onFind: (String? filter) async {
asyncItems: (String filter) async {
final boutWeightClasses = await availableWeightClasses;
return (filter == null
? boutWeightClasses
: boutWeightClasses.where((element) => element.name.contains(filter)))
.toList();
return boutWeightClasses.toList();
},
),
),
Expand Down Expand Up @@ -234,7 +231,7 @@ class ParticipantSelectTile extends ConsumerWidget {
flex: 80,
child: Container(
padding: const EdgeInsets.only(right: 8, top: 8, bottom: 8),
child: getDropdown<Participation>(
child: SearchableDropdown<Participation>(
selectedItem: participation,
label: label,
context: context,
Expand All @@ -251,7 +248,7 @@ class ParticipantSelectTile extends ConsumerWidget {
}
},
itemAsString: (u) => u.membership.person.fullName,
onFind: (String? filter) => _filterParticipants(ref, filter, lineup),
asyncItems: (String filter) => _filterParticipants(ref, filter, lineup),
),
),
),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ class ClubEditState extends ConsumerState<ClubEdit> {
),
),
ListTile(
title: getDropdown<Organization>(
title: SearchableDropdown<Organization>(
icon: const Icon(Icons.corporate_fare),
selectedItem: _organization,
label: localizations.organization,
Expand All @@ -75,13 +75,10 @@ class ClubEditState extends ConsumerState<ClubEdit> {
}),
allowEmpty: false,
itemAsString: (u) => u.name,
onFind: (String? filter) async {
asyncItems: (String filter) async {
_availableOrganizations ??=
await (await ref.read(dataManagerNotifierProvider)).readMany<Organization, Null>();
return (filter == null
? _availableOrganizations!
: _availableOrganizations!.where((element) => element.name.contains(filter)))
.toList();
return _availableOrganizations!.toList();
},
),
),
Expand Down
37 changes: 26 additions & 11 deletions wrestling_scoreboard_client/lib/view/screens/edit/lineup_edit.dart
Original file line number Diff line number Diff line change
Expand Up @@ -116,33 +116,35 @@ class LineupEditState extends ConsumerState<LineupEdit> {
items: [
ListTile(title: HeadingText(widget.lineup.team.name)),
ListTile(
title: getDropdown<Membership>(
title: SearchableDropdown<Membership>(
selectedItem: _leader,
label: localizations.leader,
context: context,
onSaved: (Membership? value) => setState(() {
_leader = value;
}),
itemAsString: (u) => u.person.fullName,
onFind: (String? filter) async {
asyncItems: (String filter) async {
_memberships ??= await _getMemberships(ref, club: widget.lineup.team.club);
return _filterMemberships(ref, filter, widget.lineup, _memberships!);
},
isFilterOnline: true,
),
),
ListTile(
title: getDropdown<Membership>(
title: SearchableDropdown<Membership>(
selectedItem: _coach,
label: localizations.coach,
context: context,
onSaved: (Membership? value) => setState(() {
_coach = value;
}),
itemAsString: (u) => u.person.fullName,
onFind: (String? filter) async {
itemAsString: (u) => u.info,
asyncItems: (String filter) async {
_memberships ??= await _getMemberships(ref, club: widget.lineup.team.club);
return _filterMemberships(ref, filter, widget.lineup, _memberships!);
},
isFilterOnline: true,
),
),
..._participations.entries.map((mapEntry) {
Expand Down Expand Up @@ -233,7 +235,7 @@ class _ParticipationEditTileState extends ConsumerState<ParticipationEditTile> {
flex: 80,
child: Container(
padding: const EdgeInsets.only(right: 8, top: 8, bottom: 8),
child: getDropdown<Membership>(
child: SearchableDropdown<Membership>(
selectedItem: widget.participation?.membership,
label:
'${localizations.weightClass} ${widget.weightClass.name} ${widget.weightClass.style.abbreviation(context)}',
Expand All @@ -242,11 +244,12 @@ class _ParticipationEditTileState extends ConsumerState<ParticipationEditTile> {
_curMembership = newMembership;
},
onSaved: (Membership? newMembership) => onSave(),
itemAsString: (u) => u.person.fullName,
onFind: (String? filter) async {
itemAsString: (u) => u.info,
asyncItems: (String filter) async {
_memberships ??= await _getMemberships(ref, club: widget.lineup.team.club);
return _filterMemberships(ref, filter, widget.lineup, _memberships!);
},
isFilterOnline: true,
),
),
),
Expand Down Expand Up @@ -277,12 +280,24 @@ class _ParticipationEditTileState extends ConsumerState<ParticipationEditTile> {

Future<List<Membership>> _filterMemberships(
WidgetRef ref,
String? filter,
String filter,
Lineup lineup,
Iterable<Membership> memberships,
) async {
return (filter == null ? memberships : memberships.where((element) => element.person.fullName.contains(filter)))
.toList();
filter = filter.trim().toLowerCase();
if (filter.isEmpty) {
return memberships.toList();
}
final number = int.tryParse(filter);
if (number == null) {
return memberships.where((item) => item.person.fullName.toLowerCase().contains(filter)).toList();
}

// If filter string is a number, search for membership no or at API provider, if present.
filter = number.toString();
final filteredMemberships =
memberships.where((item) => (item.orgSyncId?.contains(filter) ?? false) || (item.no?.contains(filter) ?? false));
return filteredMemberships.toList();
}

Future<List<Membership>> _getMemberships(WidgetRef ref, {required Club club}) async {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ class _OrganizationEditState extends ConsumerState<OrganizationEdit> {
),
),
ListTile(
title: getDropdown<Organization>(
title: SearchableDropdown<Organization>(
icon: const Icon(Icons.corporate_fare),
selectedItem: _parent,
label: localizations.organization,
Expand All @@ -91,13 +91,10 @@ class _OrganizationEditState extends ConsumerState<OrganizationEdit> {
}),
allowEmpty: true,
itemAsString: (u) => u.name,
onFind: (String? filter) async {
asyncItems: (String filter) async {
_availableOrganizations ??=
await (await ref.read(dataManagerNotifierProvider)).readMany<Organization, Null>();
return (filter == null
? _availableOrganizations!
: _availableOrganizations!.where((element) => element.name.contains(filter)))
.toList();
return _availableOrganizations!.toList();
},
),
),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ abstract class PersonEditState<T extends PersonEdit> extends ConsumerState<T> im
),
),
ListTile(
title: getDropdown<Country>(
title: SearchableDropdown<Country>(
// TODO: replace icon with home_pin when available, also in overview
// https://github.com/flutter/flutter/issues/102560
icon: const Icon(Icons.location_on),
Expand All @@ -134,11 +134,11 @@ abstract class PersonEditState<T extends PersonEdit> extends ConsumerState<T> im
_nationality = value;
}),
itemAsString: (u) => '${u.nationality} (${u.isoShortName})',
onFind: (String? filter) async {
return (filter == null
? Countries.values
: Countries.values.where((element) => element.nationality.contains(filter)))
.toList();
asyncItems: (String filter) async {
return Countries.values;
},
onFilter: (Country item, String filter) {
return item.nationality.toLowerCase().contains(filter);
},
),
),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ class TeamEditState extends ConsumerState<TeamEdit> {
),
),
ListTile(
title: getDropdown<Club>(
title: SearchableDropdown<Club>(
icon: const Icon(Icons.foundation),
selectedItem: _club,
label: localizations.club,
Expand All @@ -74,12 +74,9 @@ class TeamEditState extends ConsumerState<TeamEdit> {
_club = value;
}),
itemAsString: (u) => u.name,
onFind: (String? filter) async {
asyncItems: (String filter) async {
_availableClubs ??= await (await ref.read(dataManagerNotifierProvider)).readMany<Club, Null>();
return (filter == null
? _availableClubs!
: _availableClubs!.where((element) => element.name.contains(filter)))
.toList();
return _availableClubs!.toList();
},
),
),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ class DevisionEditState extends BoutConfigEditState<DivisionEdit> {
),
),
ListTile(
title: getDropdown<Organization>(
title: SearchableDropdown<Organization>(
icon: const Icon(Icons.corporate_fare),
selectedItem: _organization,
label: localizations.organization,
Expand All @@ -137,18 +137,15 @@ class DevisionEditState extends BoutConfigEditState<DivisionEdit> {
}),
allowEmpty: false,
itemAsString: (u) => u.name,
onFind: (String? filter) async {
asyncItems: (String filter) async {
_availableOrganizations ??=
await (await ref.read(dataManagerNotifierProvider)).readMany<Organization, Null>();
return (filter == null
? _availableOrganizations!
: _availableOrganizations!.where((element) => element.name.contains(filter)))
.toList();
return _availableOrganizations!.toList();
},
),
),
ListTile(
title: getDropdown<Division>(
title: SearchableDropdown<Division>(
icon: const Icon(Icons.inventory),
selectedItem: _parentDivision,
label: localizations.division,
Expand All @@ -157,12 +154,9 @@ class DevisionEditState extends BoutConfigEditState<DivisionEdit> {
_parentDivision = value;
}),
itemAsString: (u) => u.fullname,
onFind: (String? filter) async {
asyncItems: (String filter) async {
_availableDivisions ??= await (await ref.read(dataManagerNotifierProvider)).readMany<Division, Null>();
return (filter == null
? _availableDivisions!
: _availableDivisions!.where((element) => element.fullname.contains(filter)))
.toList();
return _availableDivisions!.toList();
},
),
),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ class LeagueEditState extends ConsumerState<LeagueEdit> {
),
),
ListTile(
title: getDropdown<Division>(
title: SearchableDropdown<Division>(
icon: const Icon(Icons.inventory),
selectedItem: _division,
label: localizations.division,
Expand All @@ -115,12 +115,9 @@ class LeagueEditState extends ConsumerState<LeagueEdit> {
}),
itemAsString: (u) => u.fullname,
allowEmpty: false,
onFind: (String? filter) async {
asyncItems: (String filter) async {
_availableDivisions ??= await (await ref.read(dataManagerNotifierProvider)).readMany<Division, Null>();
return (filter == null
? _availableDivisions!
: _availableDivisions!.where((element) => element.fullname.contains(filter)))
.toList();
return _availableDivisions!.toList();
},
),
),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ class TeamEditState extends ConsumerState<LeagueTeamParticipationEdit> {

final items = [
ListTile(
title: getDropdown<Team>(
title: SearchableDropdown<Team>(
icon: const Icon(Icons.group),
selectedItem: _team,
label: localizations.team,
Expand All @@ -53,17 +53,14 @@ class TeamEditState extends ConsumerState<LeagueTeamParticipationEdit> {
_team = value;
}),
itemAsString: (u) => u.name,
onFind: (String? filter) async {
asyncItems: (String filter) async {
availableTeams ??= await (await ref.read(dataManagerNotifierProvider)).readMany<Team, Null>();
return (filter == null
? availableTeams!
: availableTeams!.where((element) => element.name.contains(filter)))
.toList();
return availableTeams!.toList();
},
),
),
ListTile(
title: getDropdown<League>(
title: SearchableDropdown<League>(
icon: const Icon(Icons.emoji_events),
selectedItem: _league,
label: localizations.league,
Expand All @@ -72,12 +69,9 @@ class TeamEditState extends ConsumerState<LeagueTeamParticipationEdit> {
_league = value;
}),
itemAsString: (u) => u.name,
onFind: (String? filter) async {
asyncItems: (String filter) async {
_availableLeagues ??= await (await ref.read(dataManagerNotifierProvider)).readMany<League, Null>();
return (filter == null
? _availableLeagues!
: _availableLeagues!.where((element) => element.name.contains(filter)))
.toList();
return _availableLeagues!.toList();
},
),
),
Expand Down
Loading

0 comments on commit edfd27c

Please sign in to comment.