-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #586 from verdigado/212-news-filter
212: Add news search and filter
- Loading branch information
Showing
31 changed files
with
853 additions
and
104 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
import 'dart:io'; | ||
|
||
import 'package:intl/intl.dart'; | ||
|
||
final dateFormatter = DateFormat.yMd(Platform.localeName); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
import 'dart:async'; | ||
import 'package:flutter/material.dart'; | ||
|
||
class Debouncer { | ||
final int milliseconds; | ||
Timer? _timer; | ||
|
||
Debouncer({this.milliseconds = 250}); | ||
|
||
void run(VoidCallback action) { | ||
if (_timer?.isActive ?? false) { | ||
_timer?.cancel(); | ||
} | ||
_timer = Timer(Duration(milliseconds: milliseconds), action); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
import 'package:gruene_app/swagger_generated_code/gruene_api.swagger.dart'; | ||
|
||
extension DivisionExtension on Division { | ||
String shortDisplayName() => level == DivisionLevel.bv ? name2 : shortName; | ||
} | ||
|
||
extension DivisionFilter on Iterable<Division> { | ||
List<Division> filterByLevel(DivisionLevel level) { | ||
final filtered = where((division) => division.level == level).toList(); | ||
filtered.sort((a, b) => a.name2.compareTo(b.name2)); | ||
return filtered; | ||
} | ||
|
||
Division bundesverband() => firstWhere((it) => it.divisionKey == '10000000'); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
import 'package:flutter/material.dart'; | ||
import 'package:gruene_app/app/utils/date.dart'; | ||
import 'package:gruene_app/i18n/translations.g.dart'; | ||
|
||
class DateRangePicker extends StatelessWidget { | ||
final void Function(DateTimeRange?) setDateRange; | ||
final DateTimeRange? dateRange; | ||
|
||
const DateRangePicker({ | ||
super.key, | ||
required this.setDateRange, | ||
required this.dateRange, | ||
}); | ||
|
||
Future<void> openDateRangePicker(BuildContext context) async { | ||
final theme = Theme.of(context); | ||
final newDateRange = await showDateRangePicker( | ||
context: context, | ||
firstDate: DateTime(1980), | ||
lastDate: DateTime.now(), | ||
initialDateRange: dateRange, | ||
barrierColor: theme.colorScheme.secondary, | ||
); | ||
setDateRange(newDateRange); | ||
} | ||
|
||
String formatDate(DateTime? date) => date == null ? '–' : dateFormatter.format(date.toLocal()); | ||
|
||
@override | ||
Widget build(BuildContext context) { | ||
final theme = Theme.of(context); | ||
return Row( | ||
children: [ | ||
SizedBox(width: 24), | ||
Text(t.common.dateFrom), | ||
SizedBox(width: 16), | ||
TextButton( | ||
onPressed: () => openDateRangePicker(context), | ||
style: TextButton.styleFrom( | ||
backgroundColor: theme.colorScheme.surfaceDim, | ||
side: BorderSide(color: theme.colorScheme.surfaceDim), | ||
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(6)), | ||
), | ||
child: SizedBox(width: 84, child: Center(child: Text(formatDate(dateRange?.start)))), | ||
), | ||
SizedBox(width: 16), | ||
Text(t.common.dateUntil), | ||
SizedBox(width: 16), | ||
TextButton( | ||
onPressed: () => openDateRangePicker(context), | ||
style: TextButton.styleFrom( | ||
backgroundColor: theme.colorScheme.surfaceDim, | ||
side: BorderSide(color: theme.colorScheme.surfaceDim), | ||
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(6)), | ||
), | ||
child: SizedBox(width: 84, child: Center(child: Text(formatDate(dateRange?.end)))), | ||
), | ||
SizedBox(width: 24), | ||
], | ||
); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
import 'package:flutter/material.dart'; | ||
import 'package:gruene_app/app/utils/utils.dart'; | ||
|
||
class ExpansionListTile extends StatelessWidget { | ||
final List<Widget> children; | ||
final String title; | ||
|
||
const ExpansionListTile({super.key, required this.children, required this.title}); | ||
|
||
@override | ||
Widget build(BuildContext context) { | ||
final theme = Theme.of(context); | ||
return Container( | ||
padding: const EdgeInsets.symmetric(horizontal: 24), | ||
color: theme.colorScheme.surface, | ||
child: ExpansionTile( | ||
shape: const Border(), | ||
title: Text(title), | ||
tilePadding: const EdgeInsets.all(0), | ||
backgroundColor: theme.colorScheme.surface, | ||
collapsedBackgroundColor: theme.colorScheme.surface, | ||
children: children.withDividers(), | ||
), | ||
); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
import 'package:flutter/material.dart'; | ||
|
||
class FullScreenDialog extends StatelessWidget { | ||
final Widget? child; | ||
final List<Widget>? appBarActions; | ||
|
||
const FullScreenDialog({super.key, this.child, this.appBarActions}); | ||
|
||
@override | ||
Widget build(BuildContext context) { | ||
final theme = Theme.of(context); | ||
return Scaffold( | ||
backgroundColor: theme.colorScheme.surfaceDim, | ||
appBar: AppBar( | ||
backgroundColor: theme.colorScheme.surfaceDim, | ||
surfaceTintColor: theme.colorScheme.surfaceDim, | ||
leading: IconButton(icon: Icon(Icons.close), onPressed: Navigator.of(context).pop), | ||
actions: appBarActions, | ||
), | ||
body: child, | ||
); | ||
} | ||
} | ||
|
||
void showFullScreenDialog(BuildContext context, WidgetBuilder builder) { | ||
Navigator.of(context).push(MaterialPageRoute<void>(fullscreenDialog: true, builder: builder)); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
import 'package:flutter/material.dart'; | ||
|
||
class RoundedIconButton extends StatelessWidget { | ||
final void Function() onPressed; | ||
final IconData icon; | ||
final Color iconColor; | ||
final Color backgroundColor; | ||
final bool selected; | ||
final double width; | ||
final double height; | ||
|
||
const RoundedIconButton({ | ||
super.key, | ||
required this.onPressed, | ||
required this.icon, | ||
required this.iconColor, | ||
required this.backgroundColor, | ||
this.selected = false, | ||
this.width = 48, | ||
this.height = 48, | ||
}); | ||
|
||
@override | ||
Widget build(BuildContext context) { | ||
return Container( | ||
decoration: ShapeDecoration( | ||
shape: RoundedRectangleBorder( | ||
borderRadius: BorderRadius.circular(10), | ||
side: BorderSide(color: selected ? backgroundColor : iconColor, width: 1), | ||
), | ||
), | ||
child: Container( | ||
width: width, | ||
height: height, | ||
decoration: ShapeDecoration( | ||
color: selected ? iconColor : backgroundColor, | ||
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(10)), | ||
), | ||
child: IconButton( | ||
icon: Icon(icon, color: selected ? backgroundColor : iconColor), | ||
onPressed: onPressed, | ||
style: IconButton.styleFrom(shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(10))), | ||
), | ||
), | ||
); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
import 'package:flutter/material.dart'; | ||
import 'package:gruene_app/app/theme/theme.dart'; | ||
import 'package:gruene_app/app/utils/debouncer.dart'; | ||
import 'package:gruene_app/i18n/translations.g.dart'; | ||
|
||
class CustomSearchBar extends StatefulWidget { | ||
final void Function(String selected) setQuery; | ||
final String query; | ||
|
||
const CustomSearchBar({super.key, required this.setQuery, required this.query}); | ||
|
||
@override | ||
State<CustomSearchBar> createState() => _CustomSearchBarState(); | ||
} | ||
|
||
class _CustomSearchBarState extends State<CustomSearchBar> { | ||
final Debouncer _debouncer = Debouncer(); | ||
final _controller = TextEditingController(); | ||
|
||
@override | ||
Widget build(BuildContext context) { | ||
final theme = Theme.of(context); | ||
return SearchBar( | ||
controller: _controller, | ||
onTapOutside: (_) => FocusManager.instance.primaryFocus?.unfocus(), | ||
onChanged: (query) => _debouncer.run(() => widget.setQuery(query)), | ||
leading: Icon(Icons.search_outlined, color: ThemeColors.textDisabled), | ||
hintText: t.common.search, | ||
hintStyle: WidgetStatePropertyAll(const TextStyle(color: ThemeColors.textDisabled)), | ||
trailing: widget.query.isNotEmpty | ||
? [ | ||
IconButton( | ||
onPressed: () { | ||
_controller.clear(); | ||
widget.setQuery(''); | ||
}, | ||
icon: Icon(Icons.clear, color: ThemeColors.textDisabled), | ||
), | ||
] | ||
: [], | ||
backgroundColor: WidgetStatePropertyAll(theme.colorScheme.surface), | ||
padding: WidgetStatePropertyAll(EdgeInsets.only(left: 8)), | ||
shape: WidgetStatePropertyAll( | ||
RoundedRectangleBorder( | ||
borderRadius: BorderRadius.circular(12), | ||
side: BorderSide(color: ThemeColors.textDisabled), | ||
), | ||
), | ||
elevation: WidgetStatePropertyAll(0), | ||
); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
import 'package:flutter/material.dart'; | ||
import 'package:gruene_app/app/theme/theme.dart'; | ||
import 'package:gruene_app/app/widgets/text_list_item.dart'; | ||
|
||
class SelectionListItem extends StatelessWidget { | ||
final void Function() toggleSelection; | ||
final String title; | ||
final bool selected; | ||
|
||
const SelectionListItem({super.key, required this.title, required this.toggleSelection, required this.selected}); | ||
|
||
@override | ||
Widget build(BuildContext context) { | ||
final theme = Theme.of(context); | ||
return TextListItem( | ||
onPress: toggleSelection, | ||
title: title, | ||
trailing: Container( | ||
width: 24, | ||
height: 24, | ||
decoration: BoxDecoration( | ||
shape: BoxShape.circle, | ||
color: selected ? theme.colorScheme.secondary : theme.colorScheme.surface, | ||
border: Border.all(width: 2, color: selected ? theme.colorScheme.secondary : ThemeColors.textDisabled), | ||
), | ||
child: Checkbox( | ||
value: selected, | ||
checkColor: theme.colorScheme.surface, | ||
activeColor: theme.colorScheme.secondary, | ||
onChanged: (_) => toggleSelection(), | ||
shape: CircleBorder(), | ||
side: BorderSide.none, | ||
), | ||
), | ||
); | ||
} | ||
} |
Oops, something went wrong.