diff --git a/lib/view/pages/more/abiturCalculator/abiturCalculatorStep.dart b/lib/view/pages/more/abiturCalculator/abiturCalculatorStep.dart new file mode 100644 index 0000000..564a6ad --- /dev/null +++ b/lib/view/pages/more/abiturCalculator/abiturCalculatorStep.dart @@ -0,0 +1,9 @@ +import 'package:flutter/material.dart'; + +import 'models/subject.dart'; + +abstract class AbiturCalculatorStep extends Step { + const AbiturCalculatorStep({required super.title, required super.content}); + + bool canGoNextStep(SubjectCollection subjects); +} \ No newline at end of file diff --git a/lib/view/pages/more/abiturCalculator/abiturCalculatorView.dart b/lib/view/pages/more/abiturCalculator/abiturCalculatorView.dart index 5a40735..248644c 100644 --- a/lib/view/pages/more/abiturCalculator/abiturCalculatorView.dart +++ b/lib/view/pages/more/abiturCalculator/abiturCalculatorView.dart @@ -1,11 +1,7 @@ import 'package:flutter/material.dart'; +import '../../../../widget/confirmDialog.dart'; import 'models/abiturCalculatorModel.dart'; import 'models/subject.dart'; -import 'steps/resultStep.dart'; -import 'steps/selectGkStep.dart'; -import 'steps/selectLkStep.dart'; -import 'steps/selectPfStep.dart'; -import 'steps/welcomeStep.dart'; import 'package:provider/provider.dart'; class AbiturCalculatorView extends StatelessWidget { @@ -33,18 +29,26 @@ class AbiturCalculatorView extends StatelessWidget { return Scaffold( appBar: AppBar( title: const Text('Abitur Notenrechner'), + actions: [ + IconButton( + onPressed: () => ConfirmDialog( + title: 'Zurücksetzen', + content: 'Alle Felder werden zurückgesetzt', + confirmButton: 'Löschen', + onConfirm: state.reset, + ).asDialog(context), + icon: const Icon(Icons.delete_outline_outlined), + ) + ], ), body: Stepper( type: StepperType.vertical, - steps: [ - const WelcomeStep(), - SelectLkStep(), - SelectGkStep(), - const SelectPfStep(), - const ResultStep(), - ], - currentStep: state.getStep, - onStepTapped: (step) => state.setStep = step, + steps: state.getSteps, + currentStep: state.getCurrentStepIndex, + + onStepContinue: () => state.increaseStep(), + onStepCancel: () => state.decreaseStep(), + stepIconBuilder: (stepIndex, stepState) => _stepIconBuilder(context, stepIndex, stepState), controlsBuilder: _controlsBuilder, ) @@ -57,9 +61,9 @@ class AbiturCalculatorView extends StatelessWidget { return Container( decoration: BoxDecoration( borderRadius: BorderRadius.circular(20), - color: state.getStep == stepIndex + color: state.getCurrentStepIndex == stepIndex ? Theme.of(context).primaryColor - : Theme.of(context).colorScheme.surface, + : Theme.of(context).colorScheme.surfaceVariant, ), child: Center( child: Text((++stepIndex).toString()), @@ -68,7 +72,18 @@ class AbiturCalculatorView extends StatelessWidget { }); } - Widget _controlsBuilder(BuildContext context, details) { - return const Row(children: [SizedBox.shrink()]); + Widget _controlsBuilder(BuildContext context, ControlsDetails details) { + return Row( + children: [ + TextButton( + onPressed: details.onStepCancel, + child: const Text('Zurück'), + ), + TextButton( + onPressed: details.onStepContinue, + child: const Text('Weiter'), + ), + ] + ); } } \ No newline at end of file diff --git a/lib/view/pages/more/abiturCalculator/models/abiturCalculatorModel.dart b/lib/view/pages/more/abiturCalculator/models/abiturCalculatorModel.dart index 794acba..0a17b2d 100644 --- a/lib/view/pages/more/abiturCalculator/models/abiturCalculatorModel.dart +++ b/lib/view/pages/more/abiturCalculator/models/abiturCalculatorModel.dart @@ -1,52 +1,77 @@ import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; +import '../abiturCalculatorStep.dart'; +import '../steps/resultStep.dart'; +import '../steps/selectGkStep.dart'; +import '../steps/selectLkStep.dart'; +import '../steps/selectPfStep.dart'; +import '../steps/welcomeStep.dart'; import 'subject.dart'; class AbiturCalculatorModel extends ChangeNotifier { - static SubjectCollection subjects = SubjectCollection([ - Subject(displayName: 'Deutsch', icon: Icons.translate_outlined, lkApplicable: true), - Subject(displayName: 'Erste Fremdsprache', icon: Icons.translate_outlined, lkApplicable: true), - Subject(displayName: 'Zweite Fremdsprache', icon: Icons.translate_outlined, lkApplicable: true), - Subject(displayName: 'Zweite Fremdsprache ab Kl. 11', icon: Icons.translate_outlined, lkApplicable: false), - Subject(displayName: 'Kunst', icon: Icons.brush_outlined, lkApplicable: true), - Subject(displayName: 'Musik', icon: Icons.music_note_outlined, lkApplicable: true), - Subject(displayName: 'Darstellendes Spiel', icon: Icons.theater_comedy_outlined, lkApplicable: false), - Subject(displayName: 'PoWi', icon: Icons.book_outlined, lkApplicable: true), - Subject(displayName: 'Geschichte', icon: Icons.history_outlined, lkApplicable: true), - Subject(displayName: 'Religion', icon: Icons.church_outlined, lkApplicable: true), - Subject(displayName: 'Erdkunde', icon: Icons.map_outlined, lkApplicable: true), - Subject(displayName: 'Mathematik', icon: Icons.calculate_outlined, lkApplicable: true), - Subject(displayName: 'Erste Naturwissenschaft', icon: Icons.science_outlined, lkApplicable: true), - Subject(displayName: 'Zweite Naturwissenschaft', icon: Icons.science_outlined, lkApplicable: true), - Subject(displayName: 'Dritte Naturwissenschaft', icon: Icons.science_outlined, lkApplicable: true), - Subject(displayName: 'Biochemie', icon: Icons.biotech_outlined, lkApplicable: false), - Subject(displayName: 'Informatik', icon: Icons.code_outlined, lkApplicable: true), - Subject(displayName: 'Sport', icon: Icons.sports_basketball_outlined, lkApplicable: true), + static final SubjectCollection _collection = SubjectCollection([ + Subject(displayName: 'Deutsch', icon: Icons.translate_outlined, canBeLk: true, importantLk: true), + Subject(displayName: 'Erste Fremdsprache', icon: Icons.translate_outlined, canBeLk: true, importantLk: true), + Subject(displayName: 'Zweite Fremdsprache', icon: Icons.translate_outlined, canBeLk: true, importantLk: true), + Subject(displayName: 'Zweite Fremdsprache ab Kl. 11', icon: Icons.translate_outlined, canBeLk: false, importantLk: false), + Subject(displayName: 'Kunst', icon: Icons.brush_outlined, canBeLk: true, importantLk: false), + Subject(displayName: 'Musik', icon: Icons.music_note_outlined, canBeLk: true, importantLk: false), + Subject(displayName: 'Darstellendes Spiel', icon: Icons.theater_comedy_outlined, canBeLk: false, importantLk: false), + Subject(displayName: 'PoWi', icon: Icons.book_outlined, canBeLk: true, importantLk: false), + Subject(displayName: 'Geschichte', icon: Icons.history_outlined, canBeLk: true, importantLk: false), + Subject(displayName: 'Religion', icon: Icons.church_outlined, canBeLk: true, importantLk: false), + Subject(displayName: 'Erdkunde', icon: Icons.map_outlined, canBeLk: true, importantLk: false), + Subject(displayName: 'Mathematik', icon: Icons.calculate_outlined, canBeLk: true, importantLk: true), + Subject(displayName: 'Chemie', icon: Icons.science_outlined, canBeLk: true, importantLk: true), + Subject(displayName: 'Physik', icon: Icons.add, canBeLk: true, importantLk: true), + Subject(displayName: 'Biologie', icon: Icons.add, canBeLk: true, importantLk: true), + Subject(displayName: 'Biochemie', icon: Icons.biotech_outlined, canBeLk: false, importantLk: false), + Subject(displayName: 'Informatik', icon: Icons.code_outlined, canBeLk: true, importantLk: false), + Subject(displayName: 'Sport', icon: Icons.sports_basketball_outlined, canBeLk: true, importantLk: false), ]); + static final List _steps = [ + const WelcomeStep(), + SelectLkStep(), + SelectGkStep(), + const SelectPfStep(), + const ResultStep(), + ]; + + List get getSteps => _steps; + AbiturCalculatorStep getCurrentStep() => _steps[getCurrentStepIndex]; + static AbiturCalculatorModel get(BuildContext context) { return Provider.of(context, listen: false); } - late SubjectCollection _collection; int _currentStep = 0; - SubjectCollection get getSubjects => _collection; - void updateSubjects(void Function(SubjectCollection collection) callback) { - callback(_collection); + SubjectCollection getSubjects({bool update = false}) { + if(update) notifyListeners(); + return _collection; + } + + void update() { notifyListeners(); } - int get getStep => _currentStep; - set setStep(int step) { - _currentStep = step; + int get getCurrentStepIndex => _currentStep; + void increaseStep() { + if(getCurrentStep().canGoNextStep(getSubjects())) _currentStep++; + notifyListeners(); + } + void decreaseStep() { + if(_currentStep >= 1) _currentStep--; notifyListeners(); } void reset() { _currentStep = 0; - _collection = subjects; + for (var e in _collection.collection) { + e.reset(); + } notifyListeners(); } diff --git a/lib/view/pages/more/abiturCalculator/models/subject.dart b/lib/view/pages/more/abiturCalculator/models/subject.dart index 2a9efb0..97acb76 100644 --- a/lib/view/pages/more/abiturCalculator/models/subject.dart +++ b/lib/view/pages/more/abiturCalculator/models/subject.dart @@ -19,24 +19,43 @@ class SubjectCollection { } class Subject { - String displayName; - IconData icon; - bool lkApplicable; + final String displayName; + final IconData icon; + final bool canBeLk; + final bool importantLk; SubjectState _subjectState = SubjectState.none; bool isLk() => _subjectState == SubjectState.isLk; bool isGk() => _subjectState == SubjectState.isGk; - bool canLk(List other) => lkApplicable && !isGk() && other.where((s) => s.isLk()).length < HighEduGraduationConstants.maxLks; + + bool canLk(List other) { + Subject? otherLk() => other.where((s) => s.isLk()).firstOrNull; + bool hasOtherLk() => otherLk() != null; + + return + ((hasOtherLk() && otherLk()!.importantLk) || importantLk) + && canBeLk + && !isGk() + && other.where((s) => s.isLk()).length < HighEduGraduationConstants.maxLks; + } + bool canGk(List other) => !isLk() && other.where((s) => s.isGk()).length < HighEduGraduationConstants.maxGks; set unsafeSubjectSet(SubjectState newState) => _subjectState = newState; set unsafeLkToggle(bool isLk) { + if(isLk) { + + } _subjectState = isLk ? SubjectState.isLk : SubjectState.none; } set unsafeGkToggle(bool isGk) { _subjectState = isGk ? SubjectState.isGk : SubjectState.none; } - Subject({required this.displayName, required this.icon, required this.lkApplicable}); + void reset() { + _subjectState = SubjectState.none; + } + + Subject({required this.displayName, required this.icon, required this.canBeLk, required this.importantLk}); } \ No newline at end of file diff --git a/lib/view/pages/more/abiturCalculator/steps/resultStep.dart b/lib/view/pages/more/abiturCalculator/steps/resultStep.dart index c03b67d..72b4c61 100644 --- a/lib/view/pages/more/abiturCalculator/steps/resultStep.dart +++ b/lib/view/pages/more/abiturCalculator/steps/resultStep.dart @@ -1,8 +1,16 @@ import 'package:flutter/material.dart'; -class ResultStep extends Step { +import '../abiturCalculatorStep.dart'; +import '../models/subject.dart'; + +class ResultStep extends AbiturCalculatorStep { const ResultStep() : super( title: const Text('Ergebnis'), content: const SizedBox.shrink(), ); + + @override + bool canGoNextStep(SubjectCollection subjects) { + throw UnimplementedError(); + } } \ No newline at end of file diff --git a/lib/view/pages/more/abiturCalculator/steps/selectGkStep.dart b/lib/view/pages/more/abiturCalculator/steps/selectGkStep.dart index 22ca463..f522994 100644 --- a/lib/view/pages/more/abiturCalculator/steps/selectGkStep.dart +++ b/lib/view/pages/more/abiturCalculator/steps/selectGkStep.dart @@ -1,23 +1,54 @@ import 'package:flutter/material.dart'; +import '../../../../../widget/centeredLeading.dart'; +import '../../../../../widget/providerBridge.dart'; +import '../abiturCalculatorStep.dart'; import '../abiturCalculatorView.dart'; import '../models/abiturCalculatorModel.dart'; +import '../models/subject.dart'; -class SelectGkStep extends Step { +class SelectGkStep extends AbiturCalculatorStep { SelectGkStep() : super( title: const Text('Grundkurse'), content: Builder(builder: (context) { - var gkSubjects = AbiturCalculatorModel.get(context).getSubjects.collection.where((e) => e.isGk()).toList(); + var model = AbiturCalculatorModel.get(context); + var gkSubjects = model.getSubjects().collection.where((e) => e.isGk()).toList(); return Column( children: [ AbiturCalculatorView.listSubjects(gkSubjects), TextButton( onPressed: () { - // showDialog( - // context: context, - // barrierDismissible: false, - // builder: (context) => const SelectGkDialog(), - // ); + ProviderBridge.toDialog(context, model, (context, value) { + return AlertDialog( + title: const Text('Grundkurse'), + content: SingleChildScrollView( + child: Column( + mainAxisSize: MainAxisSize.min, + children: model.getSubjects().collection.map((e) { + return ListTile( + leading: CenteredLeading(Icon(e.icon)), + title: Text(e.displayName), + trailing: Checkbox( + value: e.isGk(), + onChanged: e.isGk() || e.canGk(model.getSubjects().collection) ? (value) { + e.unsafeGkToggle = value!; + model.update(); + } : null, + ), + ); + }).toList(), + ), + ), + actions: [ + TextButton( + onPressed: () { + Navigator.of(context).pop(); + }, + child: const Text('Fertig'), + ) + ], + ); + }); }, child: Text( "Grundkurse ${gkSubjects.isEmpty ? "auswählen" : "ändern"}"), @@ -26,4 +57,10 @@ class SelectGkStep extends Step { ); }), ); + + @override + bool canGoNextStep(SubjectCollection subjects) { + // TODO: implement canGoNextStepp + throw UnimplementedError(); + } } \ No newline at end of file diff --git a/lib/view/pages/more/abiturCalculator/steps/selectLkStep.dart b/lib/view/pages/more/abiturCalculator/steps/selectLkStep.dart index 6fa6327..5b558fb 100644 --- a/lib/view/pages/more/abiturCalculator/steps/selectLkStep.dart +++ b/lib/view/pages/more/abiturCalculator/steps/selectLkStep.dart @@ -2,15 +2,17 @@ import 'package:flutter/material.dart'; import '../../../../../widget/providerBridge.dart'; import '../../../../../widget/centeredLeading.dart'; +import '../abiturCalculatorStep.dart'; import '../abiturCalculatorView.dart'; import '../models/abiturCalculatorModel.dart'; +import '../models/subject.dart'; -class SelectLkStep extends Step { +class SelectLkStep extends AbiturCalculatorStep { SelectLkStep() : super( title: const Text('Leistungskurse'), content: StatefulBuilder(builder: (context, setState) { var model = AbiturCalculatorModel.get(context); - var lkSubjects = model.getSubjects.collection.where((e) => e.isLk()).toList(); + var lkSubjects = model.getSubjects().collection.where((e) => e.isLk()).toList(); return Column( children: [ AbiturCalculatorView.listSubjects(lkSubjects), @@ -22,16 +24,15 @@ class SelectLkStep extends Step { content: SingleChildScrollView( child: Column( mainAxisSize: MainAxisSize.min, - children: model.getSubjects.collection.map((e) { + children: model.getSubjects().collection.map((e) { return ListTile( leading: CenteredLeading(Icon(e.icon)), title: Text(e.displayName), trailing: Checkbox( value: e.isLk(), - onChanged: e.isLk() || e.canLk(model.getSubjects.collection) ? (value) { - model.updateSubjects((collection) { - e.unsafeLkToggle = value!; - }); + onChanged: e.isLk() || e.canLk(model.getSubjects().collection) ? (value) { + e.unsafeLkToggle = value!; + model.update(); } : null, ), ); @@ -55,6 +56,11 @@ class SelectLkStep extends Step { ); }), ); + + @override + bool canGoNextStep(SubjectCollection subjects) { + return subjects.collection.where((element) => element.isLk()).length >= 2; + } } class SelectLkStepTest extends StatelessWidget { const SelectLkStepTest({super.key}); diff --git a/lib/view/pages/more/abiturCalculator/steps/selectPfStep.dart b/lib/view/pages/more/abiturCalculator/steps/selectPfStep.dart index cce67c5..6443e67 100644 --- a/lib/view/pages/more/abiturCalculator/steps/selectPfStep.dart +++ b/lib/view/pages/more/abiturCalculator/steps/selectPfStep.dart @@ -1,8 +1,17 @@ import 'package:flutter/material.dart'; -class SelectPfStep extends Step { +import '../abiturCalculatorStep.dart'; +import '../models/subject.dart'; + +class SelectPfStep extends AbiturCalculatorStep { const SelectPfStep() : super( title: const Text('Prüfungsfächer'), content: const SizedBox.shrink(), ); + + @override + bool canGoNextStep(SubjectCollection subjects) { + // TODO: implement canGoNextStepp + throw UnimplementedError(); + } } \ No newline at end of file diff --git a/lib/view/pages/more/abiturCalculator/steps/welcomeStep.dart b/lib/view/pages/more/abiturCalculator/steps/welcomeStep.dart index dc67e16..9def7b1 100644 --- a/lib/view/pages/more/abiturCalculator/steps/welcomeStep.dart +++ b/lib/view/pages/more/abiturCalculator/steps/welcomeStep.dart @@ -1,8 +1,16 @@ import 'package:flutter/material.dart'; -class WelcomeStep extends Step { +import '../abiturCalculatorStep.dart'; +import '../models/subject.dart'; + +class WelcomeStep extends AbiturCalculatorStep { const WelcomeStep() : super( title: const Text('Willkommen'), content: const Text('In den folgenden Schritten werden alle nötigen Informationen zur Ermittlung deiner Abiturzulassung abgefragt.') ); + + @override + bool canGoNextStep(SubjectCollection subjects) { + return true; + } } \ No newline at end of file