revamp on bloc approach
This commit is contained in:
		| @@ -1,10 +0,0 @@ | ||||
|  | ||||
| import '../../../infrastructure/controller.dart'; | ||||
| import 'grade_averages_state.dart'; | ||||
|  | ||||
| class GradeAveragesController extends Controller<GradeAveragesState> { | ||||
|   GradeAveragesController(super.initialState); | ||||
|  | ||||
|   void setGradeType(GradingSchemes scheme) => emit(state.copyWith(gradingScheme: scheme)); | ||||
|   double average() => state.grades.reduce((a, b) => a + b) / state.grades.length; | ||||
| } | ||||
| @@ -1,24 +0,0 @@ | ||||
| import '../../../infrastructure/controller.dart'; | ||||
| import '../../../infrastructure/loadable_state.dart'; | ||||
| import 'marianum_message_state.dart'; | ||||
|  | ||||
| class MarianumMessageController extends Controller<LoadableState<MarianumMessageState>> { | ||||
|   MarianumMessageController() : super(const LoadableState(loadingState: LoadingState.none, data: MarianumMessageState(test: []))); | ||||
|  | ||||
|   void loading() { | ||||
|     emit(state.loading()); | ||||
|     Future.delayed(const Duration(seconds: 3)).then((value) => emit(state.done(const MarianumMessageState(test: [])))); | ||||
|   } | ||||
|    | ||||
|   void backgroundLoading() { | ||||
|     emit(state.cached(const MarianumMessageState(test: []))); | ||||
|   } | ||||
|  | ||||
|   void done() { | ||||
|     emit(state.done(const MarianumMessageState(test: []))); | ||||
|   } | ||||
|  | ||||
|   void error() { | ||||
|     emit(state.error(state: const MarianumMessageState(test: []))); | ||||
|   } | ||||
| } | ||||
| @@ -1,10 +0,0 @@ | ||||
| import 'package:freezed_annotation/freezed_annotation.dart'; | ||||
|  | ||||
| part 'marianum_message_state.freezed.dart'; | ||||
|  | ||||
| @freezed | ||||
| class MarianumMessageState with _$MarianumMessageState { | ||||
|   const factory MarianumMessageState({ | ||||
|     required List<String> test | ||||
|   }) = _MarianumMessageState; | ||||
| } | ||||
| @@ -1,143 +0,0 @@ | ||||
| // coverage:ignore-file | ||||
| // GENERATED CODE - DO NOT MODIFY BY HAND | ||||
| // ignore_for_file: type=lint | ||||
| // ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark | ||||
|  | ||||
| part of 'marianum_message_state.dart'; | ||||
|  | ||||
| // ************************************************************************** | ||||
| // FreezedGenerator | ||||
| // ************************************************************************** | ||||
|  | ||||
| T _$identity<T>(T value) => value; | ||||
|  | ||||
| final _privateConstructorUsedError = UnsupportedError( | ||||
|     'It seems like you constructed your class using `MyClass._()`. This constructor is only meant to be used by freezed and you are not supposed to need it nor use it.\nPlease check the documentation here for more information: https://github.com/rrousselGit/freezed#adding-getters-and-methods-to-our-models'); | ||||
|  | ||||
| /// @nodoc | ||||
| mixin _$MarianumMessageState { | ||||
|   List<String> get test => throw _privateConstructorUsedError; | ||||
|  | ||||
|   @JsonKey(ignore: true) | ||||
|   $MarianumMessageStateCopyWith<MarianumMessageState> get copyWith => | ||||
|       throw _privateConstructorUsedError; | ||||
| } | ||||
|  | ||||
| /// @nodoc | ||||
| abstract class $MarianumMessageStateCopyWith<$Res> { | ||||
|   factory $MarianumMessageStateCopyWith(MarianumMessageState value, | ||||
|           $Res Function(MarianumMessageState) then) = | ||||
|       _$MarianumMessageStateCopyWithImpl<$Res, MarianumMessageState>; | ||||
|   @useResult | ||||
|   $Res call({List<String> test}); | ||||
| } | ||||
|  | ||||
| /// @nodoc | ||||
| class _$MarianumMessageStateCopyWithImpl<$Res, | ||||
|         $Val extends MarianumMessageState> | ||||
|     implements $MarianumMessageStateCopyWith<$Res> { | ||||
|   _$MarianumMessageStateCopyWithImpl(this._value, this._then); | ||||
|  | ||||
|   // ignore: unused_field | ||||
|   final $Val _value; | ||||
|   // ignore: unused_field | ||||
|   final $Res Function($Val) _then; | ||||
|  | ||||
|   @pragma('vm:prefer-inline') | ||||
|   @override | ||||
|   $Res call({ | ||||
|     Object? test = null, | ||||
|   }) { | ||||
|     return _then(_value.copyWith( | ||||
|       test: null == test | ||||
|           ? _value.test | ||||
|           : test // ignore: cast_nullable_to_non_nullable | ||||
|               as List<String>, | ||||
|     ) as $Val); | ||||
|   } | ||||
| } | ||||
|  | ||||
| /// @nodoc | ||||
| abstract class _$$MarianumMessageStateImplCopyWith<$Res> | ||||
|     implements $MarianumMessageStateCopyWith<$Res> { | ||||
|   factory _$$MarianumMessageStateImplCopyWith(_$MarianumMessageStateImpl value, | ||||
|           $Res Function(_$MarianumMessageStateImpl) then) = | ||||
|       __$$MarianumMessageStateImplCopyWithImpl<$Res>; | ||||
|   @override | ||||
|   @useResult | ||||
|   $Res call({List<String> test}); | ||||
| } | ||||
|  | ||||
| /// @nodoc | ||||
| class __$$MarianumMessageStateImplCopyWithImpl<$Res> | ||||
|     extends _$MarianumMessageStateCopyWithImpl<$Res, _$MarianumMessageStateImpl> | ||||
|     implements _$$MarianumMessageStateImplCopyWith<$Res> { | ||||
|   __$$MarianumMessageStateImplCopyWithImpl(_$MarianumMessageStateImpl _value, | ||||
|       $Res Function(_$MarianumMessageStateImpl) _then) | ||||
|       : super(_value, _then); | ||||
|  | ||||
|   @pragma('vm:prefer-inline') | ||||
|   @override | ||||
|   $Res call({ | ||||
|     Object? test = null, | ||||
|   }) { | ||||
|     return _then(_$MarianumMessageStateImpl( | ||||
|       test: null == test | ||||
|           ? _value._test | ||||
|           : test // ignore: cast_nullable_to_non_nullable | ||||
|               as List<String>, | ||||
|     )); | ||||
|   } | ||||
| } | ||||
|  | ||||
| /// @nodoc | ||||
|  | ||||
| class _$MarianumMessageStateImpl implements _MarianumMessageState { | ||||
|   const _$MarianumMessageStateImpl({required final List<String> test}) | ||||
|       : _test = test; | ||||
|  | ||||
|   final List<String> _test; | ||||
|   @override | ||||
|   List<String> get test { | ||||
|     if (_test is EqualUnmodifiableListView) return _test; | ||||
|     // ignore: implicit_dynamic_type | ||||
|     return EqualUnmodifiableListView(_test); | ||||
|   } | ||||
|  | ||||
|   @override | ||||
|   String toString() { | ||||
|     return 'MarianumMessageState(test: $test)'; | ||||
|   } | ||||
|  | ||||
|   @override | ||||
|   bool operator ==(Object other) { | ||||
|     return identical(this, other) || | ||||
|         (other.runtimeType == runtimeType && | ||||
|             other is _$MarianumMessageStateImpl && | ||||
|             const DeepCollectionEquality().equals(other._test, _test)); | ||||
|   } | ||||
|  | ||||
|   @override | ||||
|   int get hashCode => | ||||
|       Object.hash(runtimeType, const DeepCollectionEquality().hash(_test)); | ||||
|  | ||||
|   @JsonKey(ignore: true) | ||||
|   @override | ||||
|   @pragma('vm:prefer-inline') | ||||
|   _$$MarianumMessageStateImplCopyWith<_$MarianumMessageStateImpl> | ||||
|       get copyWith => | ||||
|           __$$MarianumMessageStateImplCopyWithImpl<_$MarianumMessageStateImpl>( | ||||
|               this, _$identity); | ||||
| } | ||||
|  | ||||
| abstract class _MarianumMessageState implements MarianumMessageState { | ||||
|   const factory _MarianumMessageState({required final List<String> test}) = | ||||
|       _$MarianumMessageStateImpl; | ||||
|  | ||||
|   @override | ||||
|   List<String> get test; | ||||
|   @override | ||||
|   @JsonKey(ignore: true) | ||||
|   _$$MarianumMessageStateImplCopyWith<_$MarianumMessageStateImpl> | ||||
|       get copyWith => throw _privateConstructorUsedError; | ||||
| } | ||||
							
								
								
									
										29
									
								
								lib/state/app/modules/app_modules.dart
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										29
									
								
								lib/state/app/modules/app_modules.dart
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,29 @@ | ||||
| import 'package:flutter/material.dart'; | ||||
|  | ||||
| import '../../../view/pages/files/files.dart'; | ||||
| import '../../../view/pages/talk/chatList.dart'; | ||||
| import '../../../view/pages/timetable/timetable.dart'; | ||||
|  | ||||
| class AppModule { | ||||
|   String name; | ||||
|   IconData icon; | ||||
|   Widget Function() create; | ||||
|  | ||||
|   AppModule(this.name, this.icon, this.create); | ||||
|  | ||||
|   static Map<Module, AppModule> modules() => { | ||||
|     Module.timetable: AppModule('Vertretung', Icons.calendar_month, Timetable.new), | ||||
|     Module.talk: AppModule('Talk', Icons.chat, ChatList.new), | ||||
|     Module.files: AppModule('Files', Icons.folder, Files.new), | ||||
|   }; | ||||
| } | ||||
|  | ||||
| enum Module { | ||||
|   timetable, | ||||
|   talk, | ||||
|   files, | ||||
|   marianumMessage, | ||||
|   roomPlan, | ||||
|   gradeAveragesCalculator, | ||||
|   holidays, | ||||
| } | ||||
| @@ -0,0 +1,49 @@ | ||||
| import 'package:hydrated_bloc/hydrated_bloc.dart'; | ||||
|  | ||||
| import 'grade_averages_event.dart'; | ||||
| import 'grade_averages_state.dart'; | ||||
|  | ||||
| class GradeAveragesBloc extends HydratedBloc<GradeAveragesEvent, GradeAveragesState> { | ||||
|   GradeAveragesBloc() : super(const GradeAveragesState(gradingSystem: GradeAveragesGradingSystem.middleSchool, grades: [])) { | ||||
|  | ||||
|     on<GradingSystemChanged>((event, emit) { | ||||
|       add(ResetAll()); | ||||
|       emit( | ||||
|         state.copyWith( | ||||
|           gradingSystem: event.isMiddleSchool | ||||
|             ? GradeAveragesGradingSystem.middleSchool | ||||
|             : GradeAveragesGradingSystem.highSchool | ||||
|         ) | ||||
|       ); | ||||
|     }); | ||||
|  | ||||
|     on<ResetAll>((event, emit) { | ||||
|       emit(state.copyWith(grades: [])); | ||||
|     }); | ||||
|  | ||||
|     on<ResetGrade>((event, emit) { | ||||
|       emit(state.copyWith(grades: [...state.grades]..removeWhere((grade) => grade == event.grade))); | ||||
|     }); | ||||
|  | ||||
|     on<IncrementGrade>((event, emit) { | ||||
|       emit(state.copyWith(grades: [...state.grades, event.grade])); | ||||
|     }); | ||||
|  | ||||
|     on<DecrementGrade>((event, emit) { | ||||
|       emit(state.copyWith(grades: List.from(state.grades)..remove(event.grade))); | ||||
|     }); | ||||
|  | ||||
|   } | ||||
|  | ||||
|   double average() => state.grades.isEmpty ? 0 : state.grades.reduce((a, b) => a + b) / state.grades.length; | ||||
|   bool isMiddleSchool() => state.gradingSystem == GradeAveragesGradingSystem.middleSchool; | ||||
|   bool canDecrementOrDelete(int grade) => state.grades.contains(grade); | ||||
|   int countOfGrade(int grade) => state.grades.where((g) => g == grade).length; | ||||
|   int gradesInGradingSystem() => state.gradingSystem == GradeAveragesGradingSystem.middleSchool ? 6 : 16; | ||||
|   int getGradeFromIndex(int index) => isMiddleSchool() ? index + 1 : 15 - index; | ||||
|  | ||||
|   @override | ||||
|   GradeAveragesState? fromJson(Map<String, dynamic> json) => GradeAveragesState.fromJson(json); | ||||
|   @override | ||||
|   Map<String, dynamic>? toJson(GradeAveragesState state) => state.toJson(); | ||||
| } | ||||
| @@ -0,0 +1,20 @@ | ||||
|  | ||||
| sealed class GradeAveragesEvent {} | ||||
|  | ||||
| final class GradingSystemChanged extends GradeAveragesEvent { | ||||
|   final bool isMiddleSchool; | ||||
|   GradingSystemChanged(this.isMiddleSchool); | ||||
| } | ||||
| final class ResetAll extends GradeAveragesEvent {} | ||||
| final class ResetGrade extends GradeAveragesEvent { | ||||
|   final int grade; | ||||
|   ResetGrade(this.grade); | ||||
| } | ||||
| final class IncrementGrade extends GradeAveragesEvent { | ||||
|   final int grade; | ||||
|   IncrementGrade(this.grade); | ||||
| } | ||||
| final class DecrementGrade extends GradeAveragesEvent { | ||||
|   final int grade; | ||||
|   DecrementGrade(this.grade); | ||||
| } | ||||
| @@ -6,14 +6,14 @@ part 'grade_averages_state.g.dart'; | ||||
| @freezed | ||||
| class GradeAveragesState with _$GradeAveragesState { | ||||
|   const factory GradeAveragesState({ | ||||
|       required GradingSchemes gradingScheme, | ||||
|       required List<int> grades, | ||||
|     required GradeAveragesGradingSystem gradingSystem, | ||||
|     required List<int> grades, | ||||
|   }) = _GradeAveragesState; | ||||
| 
 | ||||
|   factory GradeAveragesState.fromJson(Map<String, dynamic> json) => _$GradeAveragesStateFromJson(json); | ||||
| } | ||||
| 
 | ||||
| enum GradingSchemes { | ||||
|   middleSchool, | ||||
| enum GradeAveragesGradingSystem { | ||||
|   highSchool, | ||||
|   middleSchool, | ||||
| } | ||||
| @@ -20,7 +20,8 @@ GradeAveragesState _$GradeAveragesStateFromJson(Map<String, dynamic> json) { | ||||
| 
 | ||||
| /// @nodoc | ||||
| mixin _$GradeAveragesState { | ||||
|   GradingSchemes get gradingScheme => throw _privateConstructorUsedError; | ||||
|   GradeAveragesGradingSystem get gradingSystem => | ||||
|       throw _privateConstructorUsedError; | ||||
|   List<int> get grades => throw _privateConstructorUsedError; | ||||
| 
 | ||||
|   Map<String, dynamic> toJson() => throw _privateConstructorUsedError; | ||||
| @@ -35,7 +36,7 @@ abstract class $GradeAveragesStateCopyWith<$Res> { | ||||
|           GradeAveragesState value, $Res Function(GradeAveragesState) then) = | ||||
|       _$GradeAveragesStateCopyWithImpl<$Res, GradeAveragesState>; | ||||
|   @useResult | ||||
|   $Res call({GradingSchemes gradingScheme, List<int> grades}); | ||||
|   $Res call({GradeAveragesGradingSystem gradingSystem, List<int> grades}); | ||||
| } | ||||
| 
 | ||||
| /// @nodoc | ||||
| @@ -51,14 +52,14 @@ class _$GradeAveragesStateCopyWithImpl<$Res, $Val extends GradeAveragesState> | ||||
|   @pragma('vm:prefer-inline') | ||||
|   @override | ||||
|   $Res call({ | ||||
|     Object? gradingScheme = null, | ||||
|     Object? gradingSystem = null, | ||||
|     Object? grades = null, | ||||
|   }) { | ||||
|     return _then(_value.copyWith( | ||||
|       gradingScheme: null == gradingScheme | ||||
|           ? _value.gradingScheme | ||||
|           : gradingScheme // ignore: cast_nullable_to_non_nullable | ||||
|               as GradingSchemes, | ||||
|       gradingSystem: null == gradingSystem | ||||
|           ? _value.gradingSystem | ||||
|           : gradingSystem // ignore: cast_nullable_to_non_nullable | ||||
|               as GradeAveragesGradingSystem, | ||||
|       grades: null == grades | ||||
|           ? _value.grades | ||||
|           : grades // ignore: cast_nullable_to_non_nullable | ||||
| @@ -75,7 +76,7 @@ abstract class _$$GradeAveragesStateImplCopyWith<$Res> | ||||
|       __$$GradeAveragesStateImplCopyWithImpl<$Res>; | ||||
|   @override | ||||
|   @useResult | ||||
|   $Res call({GradingSchemes gradingScheme, List<int> grades}); | ||||
|   $Res call({GradeAveragesGradingSystem gradingSystem, List<int> grades}); | ||||
| } | ||||
| 
 | ||||
| /// @nodoc | ||||
| @@ -89,14 +90,14 @@ class __$$GradeAveragesStateImplCopyWithImpl<$Res> | ||||
|   @pragma('vm:prefer-inline') | ||||
|   @override | ||||
|   $Res call({ | ||||
|     Object? gradingScheme = null, | ||||
|     Object? gradingSystem = null, | ||||
|     Object? grades = null, | ||||
|   }) { | ||||
|     return _then(_$GradeAveragesStateImpl( | ||||
|       gradingScheme: null == gradingScheme | ||||
|           ? _value.gradingScheme | ||||
|           : gradingScheme // ignore: cast_nullable_to_non_nullable | ||||
|               as GradingSchemes, | ||||
|       gradingSystem: null == gradingSystem | ||||
|           ? _value.gradingSystem | ||||
|           : gradingSystem // ignore: cast_nullable_to_non_nullable | ||||
|               as GradeAveragesGradingSystem, | ||||
|       grades: null == grades | ||||
|           ? _value._grades | ||||
|           : grades // ignore: cast_nullable_to_non_nullable | ||||
| @@ -109,14 +110,14 @@ class __$$GradeAveragesStateImplCopyWithImpl<$Res> | ||||
| @JsonSerializable() | ||||
| class _$GradeAveragesStateImpl implements _GradeAveragesState { | ||||
|   const _$GradeAveragesStateImpl( | ||||
|       {required this.gradingScheme, required final List<int> grades}) | ||||
|       {required this.gradingSystem, required final List<int> grades}) | ||||
|       : _grades = grades; | ||||
| 
 | ||||
|   factory _$GradeAveragesStateImpl.fromJson(Map<String, dynamic> json) => | ||||
|       _$$GradeAveragesStateImplFromJson(json); | ||||
| 
 | ||||
|   @override | ||||
|   final GradingSchemes gradingScheme; | ||||
|   final GradeAveragesGradingSystem gradingSystem; | ||||
|   final List<int> _grades; | ||||
|   @override | ||||
|   List<int> get grades { | ||||
| @@ -127,7 +128,7 @@ class _$GradeAveragesStateImpl implements _GradeAveragesState { | ||||
| 
 | ||||
|   @override | ||||
|   String toString() { | ||||
|     return 'GradeAveragesState(gradingScheme: $gradingScheme, grades: $grades)'; | ||||
|     return 'GradeAveragesState(gradingSystem: $gradingSystem, grades: $grades)'; | ||||
|   } | ||||
| 
 | ||||
|   @override | ||||
| @@ -135,15 +136,15 @@ class _$GradeAveragesStateImpl implements _GradeAveragesState { | ||||
|     return identical(this, other) || | ||||
|         (other.runtimeType == runtimeType && | ||||
|             other is _$GradeAveragesStateImpl && | ||||
|             (identical(other.gradingScheme, gradingScheme) || | ||||
|                 other.gradingScheme == gradingScheme) && | ||||
|             (identical(other.gradingSystem, gradingSystem) || | ||||
|                 other.gradingSystem == gradingSystem) && | ||||
|             const DeepCollectionEquality().equals(other._grades, _grades)); | ||||
|   } | ||||
| 
 | ||||
|   @JsonKey(ignore: true) | ||||
|   @override | ||||
|   int get hashCode => Object.hash( | ||||
|       runtimeType, gradingScheme, const DeepCollectionEquality().hash(_grades)); | ||||
|       runtimeType, gradingSystem, const DeepCollectionEquality().hash(_grades)); | ||||
| 
 | ||||
|   @JsonKey(ignore: true) | ||||
|   @override | ||||
| @@ -162,14 +163,14 @@ class _$GradeAveragesStateImpl implements _GradeAveragesState { | ||||
| 
 | ||||
| abstract class _GradeAveragesState implements GradeAveragesState { | ||||
|   const factory _GradeAveragesState( | ||||
|       {required final GradingSchemes gradingScheme, | ||||
|       {required final GradeAveragesGradingSystem gradingSystem, | ||||
|       required final List<int> grades}) = _$GradeAveragesStateImpl; | ||||
| 
 | ||||
|   factory _GradeAveragesState.fromJson(Map<String, dynamic> json) = | ||||
|       _$GradeAveragesStateImpl.fromJson; | ||||
| 
 | ||||
|   @override | ||||
|   GradingSchemes get gradingScheme; | ||||
|   GradeAveragesGradingSystem get gradingSystem; | ||||
|   @override | ||||
|   List<int> get grades; | ||||
|   @override | ||||
| @@ -9,19 +9,20 @@ part of 'grade_averages_state.dart'; | ||||
| _$GradeAveragesStateImpl _$$GradeAveragesStateImplFromJson( | ||||
|         Map<String, dynamic> json) => | ||||
|     _$GradeAveragesStateImpl( | ||||
|       gradingScheme: | ||||
|           $enumDecode(_$GradingSchemesEnumMap, json['gradingScheme']), | ||||
|       gradingSystem: $enumDecode( | ||||
|           _$GradeAveragesGradingSystemEnumMap, json['gradingSystem']), | ||||
|       grades: (json['grades'] as List<dynamic>).map((e) => e as int).toList(), | ||||
|     ); | ||||
| 
 | ||||
| Map<String, dynamic> _$$GradeAveragesStateImplToJson( | ||||
|         _$GradeAveragesStateImpl instance) => | ||||
|     <String, dynamic>{ | ||||
|       'gradingScheme': _$GradingSchemesEnumMap[instance.gradingScheme]!, | ||||
|       'gradingSystem': | ||||
|           _$GradeAveragesGradingSystemEnumMap[instance.gradingSystem]!, | ||||
|       'grades': instance.grades, | ||||
|     }; | ||||
| 
 | ||||
| const _$GradingSchemesEnumMap = { | ||||
|   GradingSchemes.middleSchool: 'middleSchool', | ||||
|   GradingSchemes.highSchool: 'highSchool', | ||||
| const _$GradeAveragesGradingSystemEnumMap = { | ||||
|   GradeAveragesGradingSystem.highSchool: 'highSchool', | ||||
|   GradeAveragesGradingSystem.middleSchool: 'middleSchool', | ||||
| }; | ||||
| @@ -0,0 +1,70 @@ | ||||
| import 'package:flutter/material.dart'; | ||||
| import 'package:provider/provider.dart'; | ||||
|  | ||||
| import '../bloc/grade_averages_bloc.dart'; | ||||
| import '../bloc/grade_averages_event.dart'; | ||||
|  | ||||
| class GradeAveragesListView extends StatelessWidget { | ||||
|   const GradeAveragesListView({super.key}); | ||||
|  | ||||
|   @override | ||||
|   Widget build(BuildContext context) { | ||||
|     var bloc = context.watch<GradeAveragesBloc>(); | ||||
|  | ||||
|     String getGradeDisplay(int grade) { | ||||
|       if(bloc.isMiddleSchool()) { | ||||
|         return 'Note $grade'; | ||||
|       } else { | ||||
|         return "$grade Punkt${grade > 1 ? "e" : ""}"; | ||||
|       } | ||||
|     } | ||||
|  | ||||
|     return ListView.builder( | ||||
|       itemCount: bloc.gradesInGradingSystem(), | ||||
|       itemBuilder: (context, index) { | ||||
|         var grade = bloc.getGradeFromIndex(index); | ||||
|         return Material( | ||||
|           child: ListTile( | ||||
|             tileColor: grade.isEven ? Colors.transparent : Colors.transparent.withAlpha(50), | ||||
|             title: Center( | ||||
|               child: Row( | ||||
|                 mainAxisAlignment: MainAxisAlignment.center, | ||||
|                 children: [ | ||||
|                   Text(getGradeDisplay(grade)), | ||||
|                   const SizedBox(width: 30), | ||||
|                   IconButton( | ||||
|                     onPressed: () { | ||||
|                       bloc.add(DecrementGrade(grade)); | ||||
|                     }, | ||||
|                     icon: const Icon(Icons.remove), | ||||
|                     color: Theme.of(context).colorScheme.onSurface, | ||||
|                   ), | ||||
|                   Text('${bloc.countOfGrade(grade)}', style: const TextStyle(fontSize: 15, fontWeight: FontWeight.bold)), | ||||
|                   IconButton( | ||||
|                     onPressed: () { | ||||
|                       bloc.add(IncrementGrade(grade)); | ||||
|                     }, | ||||
|                     icon: const Icon(Icons.add), | ||||
|                     color: Theme.of(context).colorScheme.onSurface, | ||||
|                   ), | ||||
|                 ], | ||||
|               ), | ||||
|             ), | ||||
|             trailing: Visibility( | ||||
|               maintainState: true, | ||||
|               maintainAnimation: true, | ||||
|               maintainSize: true, | ||||
|               visible: bloc.canDecrementOrDelete(grade), | ||||
|               child: IconButton( | ||||
|                 icon: const Icon(Icons.delete), | ||||
|                 onPressed: () { | ||||
|                   bloc.add(ResetGrade(grade)); | ||||
|                 }, | ||||
|               ), | ||||
|             ), | ||||
|           ), | ||||
|         ); | ||||
|       }, | ||||
|     ); | ||||
|   } | ||||
| } | ||||
| @@ -0,0 +1,98 @@ | ||||
| import 'package:flutter/material.dart'; | ||||
| import 'package:flutter_bloc/flutter_bloc.dart'; | ||||
|  | ||||
| import '../../../../../widget/confirmDialog.dart'; | ||||
| import '../bloc/grade_averages_bloc.dart'; | ||||
| import '../bloc/grade_averages_event.dart'; | ||||
| import '../bloc/grade_averages_state.dart'; | ||||
| import 'grade_averages_list_view.dart'; | ||||
|  | ||||
| class GradeAveragesScreen extends StatelessWidget { | ||||
|   const GradeAveragesScreen({super.key}); | ||||
|  | ||||
|   @override | ||||
|   Widget build(BuildContext context) => BlocProvider<GradeAveragesBloc>( | ||||
|       create: (context) => GradeAveragesBloc(), | ||||
|       child: BlocBuilder<GradeAveragesBloc, GradeAveragesState>( | ||||
|         builder: (context, state) { | ||||
|           var bloc = context.watch<GradeAveragesBloc>(); | ||||
|  | ||||
|           return Scaffold( | ||||
|           appBar: AppBar( | ||||
|             title: const Text('Notendurschnittsrechner'), | ||||
|             actions: [ | ||||
|               Visibility( | ||||
|                 visible: bloc.state.grades.isNotEmpty, | ||||
|                 child: IconButton( | ||||
|                     onPressed: () { | ||||
|                       showDialog( | ||||
|                         context: context, | ||||
|                         builder: (context) => ConfirmDialog( | ||||
|                           title: 'Zurücksetzen?', | ||||
|                           content: 'Alle Einträge werden entfernt.', | ||||
|                           confirmButton: 'Zurücksetzen', | ||||
|                           onConfirm: () { | ||||
|                             bloc.add(ResetAll()); | ||||
|                           }, | ||||
|                         ), | ||||
|                       ); | ||||
|                     }, | ||||
|                     icon: const Icon(Icons.delete_forever)), | ||||
|               ), | ||||
|               PopupMenuButton<bool>( | ||||
|                 initialValue: bloc.isMiddleSchool(), | ||||
|                 icon: const Icon(Icons.more_horiz), | ||||
|                 itemBuilder: (context) => [true, false].map((isMiddleSchool) => PopupMenuItem<bool>( | ||||
|                   value: isMiddleSchool, | ||||
|                   child: Row( | ||||
|                     children: [ | ||||
|                       Icon( | ||||
|                           isMiddleSchool ? Icons.calculate_outlined : Icons.school_outlined, | ||||
|                           color: Theme.of(context).colorScheme.onSurface | ||||
|                       ), | ||||
|                       const SizedBox(width: 15), | ||||
|                       Text(isMiddleSchool ? 'Notensystem' : 'Punktesystem'), | ||||
|                     ], | ||||
|                   ), | ||||
|                 )).toList(), | ||||
|                 onSelected: (isMiddleSchool) { | ||||
|                   if (bloc.state.grades.isNotEmpty) { | ||||
|                     showDialog( | ||||
|                       context: context, | ||||
|                       builder: (context) => ConfirmDialog( | ||||
|                         title: 'Notensystem wechseln', | ||||
|                         content: | ||||
|                         'Beim wechsel des Notensystems werden alle Einträge zurückgesetzt.', | ||||
|                         confirmButton: 'Fortfahren', | ||||
|                         onConfirm: () => bloc.add(GradingSystemChanged(isMiddleSchool)), | ||||
|                       ), | ||||
|                     ); | ||||
|                   } else { | ||||
|                     bloc.add(GradingSystemChanged(isMiddleSchool)); | ||||
|                   } | ||||
|                 }, | ||||
|               ), | ||||
|             ], | ||||
|           ), | ||||
|  | ||||
|           body: Column( | ||||
|             crossAxisAlignment: CrossAxisAlignment.center, | ||||
|             mainAxisAlignment: MainAxisAlignment.center, | ||||
|             children: [ | ||||
|               const SizedBox(height: 30), | ||||
|               Text(bloc.average().toStringAsFixed(2), style: const TextStyle(fontSize: 30, fontWeight: FontWeight.bold)), | ||||
|               const SizedBox(height: 10), | ||||
|               const Divider(), | ||||
|               const SizedBox(height: 10), | ||||
|               Text(bloc.isMiddleSchool() ? 'Wähle unten die Anzahl deiner jewiligen Noten aus' : 'Wähle unten die Anzahl deiner jeweiligen Punkte aus'), | ||||
|               const SizedBox(height: 10), | ||||
|               const Expanded( | ||||
|                 child: GradeAveragesListView() | ||||
|               ), | ||||
|             ], | ||||
|           ), | ||||
|         ); | ||||
|         }, | ||||
|       ), | ||||
|     ); | ||||
| } | ||||
		Reference in New Issue
	
	Block a user