-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: added filter for student (and teacher) plans
style: updated paddings, so it looks more modern and unified
- Loading branch information
1 parent
b7ca471
commit bdb671f
Showing
7 changed files
with
342 additions
and
19 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,106 @@ | ||
import 'dart:convert'; | ||
|
||
import 'package:hive_flutter/hive_flutter.dart'; | ||
import 'package:vertretungsapp/api/stundenplan24/models/schedule.dart'; | ||
|
||
FilterManager filterManager = FilterManager(); | ||
|
||
class Filter { | ||
final String short; | ||
final ScheduleType type; | ||
final List<String> lessons; | ||
final String schoolnumber; | ||
|
||
const Filter( | ||
{required this.short, | ||
required this.type, | ||
required this.lessons, | ||
required this.schoolnumber}); | ||
|
||
Filter.fromJson(Map<String, dynamic> json) | ||
: short = json["short"], | ||
type = ScheduleType.values[json["type"]], | ||
lessons = List<String>.from(json["lessons"]), | ||
schoolnumber = json["schoolnumber"]; | ||
|
||
Map<String, dynamic> toJson() => { | ||
"short": short, | ||
"type": type.index, | ||
"lessons": List<dynamic>.from(lessons.map((x) => x)), | ||
"schoolnumber": schoolnumber, | ||
}; | ||
|
||
void addLesson(String lesson) { | ||
lessons.add(lesson); | ||
} | ||
|
||
void removeLesson(String lesson) { | ||
lessons.remove(lesson); | ||
} | ||
|
||
bool containsLesson(String lesson) { | ||
return lessons.contains(lesson); | ||
} | ||
} | ||
|
||
class FilterManager { | ||
Map<String, List<Filter>> filters = {}; | ||
late Box<String> filterBox; | ||
|
||
FilterManager(); | ||
|
||
FilterManager.fromJson(Map<String, dynamic> json) | ||
: filters = json.map((key, value) => MapEntry(key, | ||
List<Filter>.from(value.map((x) => Filter.fromJson(x)).toList()))); | ||
|
||
Map<String, dynamic> toJson() => filters.map((key, value) => | ||
MapEntry(key, List<dynamic>.from(value.map((x) => x.toJson())))); | ||
|
||
Future<void> initFilterManager() async { | ||
filterBox = await Hive.openBox<String>("filter"); | ||
readFromDisk(); | ||
return; | ||
} | ||
|
||
FilterManager readFromDisk() { | ||
final json = filterBox.get("cache"); | ||
filters = json != null && json != "{}" | ||
? FilterManager.fromJson(jsonDecode(json)).filters | ||
: FilterManager().filters; | ||
return this; | ||
} | ||
|
||
FilterManager writeToDisk() { | ||
filterBox.put("cache", jsonEncode(toJson())); | ||
return this; | ||
} | ||
|
||
void add(Filter filter) { | ||
filters.putIfAbsent(filter.schoolnumber, () => []).add(filter); | ||
writeToDisk(); | ||
} | ||
|
||
void remove(Filter filter) { | ||
filters.putIfAbsent(filter.schoolnumber, () => []).remove(filter); | ||
writeToDisk(); | ||
} | ||
|
||
bool contains(String schoolnumber, String short) { | ||
return filters[schoolnumber] != null && | ||
filters[schoolnumber]!.any((element) => element.short == short); | ||
} | ||
|
||
Filter getFilter(String schoolnumber, String short) { | ||
if (!contains(schoolnumber, short)) { | ||
add(_createEmptyFilter(schoolnumber, short, ScheduleType.schoolClass)); | ||
} | ||
return filters[schoolnumber]! | ||
.firstWhere((element) => element.short == short); | ||
} | ||
|
||
Filter _createEmptyFilter( | ||
String schoolnumber, String short, ScheduleType type) { | ||
return Filter( | ||
short: short, type: type, lessons: [], schoolnumber: schoolnumber); | ||
} | ||
} |
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 |
---|---|---|
@@ -1,12 +1,22 @@ | ||
import 'package:flutter/material.dart'; | ||
import 'package:font_awesome_flutter/font_awesome_flutter.dart'; | ||
import 'package:vertretungsapp/components/icon_button.dart'; | ||
import 'package:vertretungsapp/pages/filter.dart'; | ||
|
||
class VPFilterButton extends StatelessWidget { | ||
const VPFilterButton({super.key}); | ||
final FilterPageData data; | ||
|
||
const VPFilterButton({super.key, required this.data}); | ||
|
||
@override | ||
Widget build(BuildContext context) { | ||
return VPIconButton(onPressed: () {}, icon: const FaIcon(FontAwesomeIcons.filter, size: 30)); | ||
return VPIconButton( | ||
onPressed: () { | ||
Navigator.push( | ||
context, | ||
MaterialPageRoute(builder: (context) => FilterPage(data: data)), | ||
); | ||
}, | ||
icon: const FaIcon(FontAwesomeIcons.filter, size: 30)); | ||
} | ||
} |
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,137 @@ | ||
import 'dart:convert'; | ||
|
||
import 'package:flutter/material.dart'; | ||
import 'package:vertretungsapp/api/filter.dart'; | ||
import 'package:vertretungsapp/api/stundenplan24/models/lesson.dart'; | ||
import 'package:vertretungsapp/api/stundenplan24/models/plan.dart'; | ||
import 'package:vertretungsapp/components/back_button.dart'; | ||
|
||
class FilterPageData { | ||
final Plan plan; | ||
final String short; | ||
final List<Lesson> lessons; | ||
final Filter filter; | ||
final void Function(Filter) onSave; | ||
|
||
const FilterPageData( | ||
{required this.plan, | ||
required this.short, | ||
required this.lessons, | ||
required this.filter, | ||
required this.onSave}); | ||
} | ||
|
||
class FilterPage extends StatelessWidget { | ||
final FilterPageData data; | ||
|
||
const FilterPage({super.key, required this.data}); | ||
|
||
@override | ||
Widget build(BuildContext context) { | ||
return Scaffold( | ||
body: Padding( | ||
padding: const EdgeInsets.fromLTRB(8, 30, 8, 0), | ||
child: Column( | ||
children: [ | ||
Row( | ||
children: [ | ||
VPBackButton(onPressed: () { | ||
data.onSave(data.filter); | ||
}), | ||
], | ||
), | ||
Center( | ||
child: RichText( | ||
text: TextSpan( | ||
text: 'Filter für ', | ||
style: Theme.of(context).textTheme.displayMedium, | ||
children: <TextSpan>[ | ||
TextSpan( | ||
text: data.short, | ||
style: TextStyle( | ||
color: Theme.of(context).colorScheme.primary)), | ||
], | ||
), | ||
), | ||
), | ||
Expanded( | ||
child: Padding( | ||
padding: const EdgeInsets.fromLTRB(0, 4, 0, 4), | ||
child: GridView.count( | ||
crossAxisCount: 3, | ||
mainAxisSpacing: 8, | ||
crossAxisSpacing: 16, | ||
childAspectRatio: 1.8, | ||
children: data.lessons | ||
.map((e) => _Item( | ||
lesson: e, | ||
filter: data.filter, | ||
)) | ||
.toList()), | ||
)) | ||
], | ||
), | ||
)); | ||
} | ||
} | ||
|
||
class _Item extends StatefulWidget { | ||
final Lesson lesson; | ||
final Filter filter; | ||
|
||
const _Item({Key? key, required this.lesson, required this.filter}) | ||
: super(key: key); | ||
|
||
@override | ||
State<_Item> createState() => _ItemState(); | ||
} | ||
|
||
class _ItemState extends State<_Item> { | ||
bool selected = true; | ||
|
||
@override | ||
void initState() { | ||
super.initState(); | ||
selected = !widget.filter.containsLesson(widget.lesson.id); | ||
} | ||
|
||
@override | ||
Widget build(BuildContext context) { | ||
return MaterialButton( | ||
shape: RoundedRectangleBorder( | ||
borderRadius: BorderRadius.circular(5), | ||
side: BorderSide( | ||
color: selected == true | ||
? Theme.of(context).colorScheme.primary | ||
: Colors.transparent, | ||
width: 0.7)), | ||
color: Theme.of(context).colorScheme.surface, | ||
onPressed: () { | ||
setState(() { | ||
selected = !selected; | ||
if (selected == false) { | ||
widget.filter.addLesson(widget.lesson.id); | ||
} else { | ||
widget.filter.removeLesson(widget.lesson.id); | ||
} | ||
}); | ||
}, | ||
child: Center( | ||
child: Column( | ||
mainAxisSize: MainAxisSize.min, | ||
children: [ | ||
Text(widget.lesson.subject), | ||
Text(widget.lesson.teacher, | ||
style: Theme.of(context) | ||
.textTheme | ||
.bodySmall! | ||
.copyWith(color: Theme.of(context).colorScheme.tertiary)), | ||
Text(widget.lesson.id, | ||
style: Theme.of(context) | ||
.textTheme | ||
.labelSmall! | ||
.copyWith(color: Theme.of(context).colorScheme.tertiary)), | ||
], | ||
))); | ||
} | ||
} |
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
Oops, something went wrong.