diff --git a/lib/main.dart b/lib/main.dart index aea08d8..225f627 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -29,6 +29,7 @@ import 'storage/base/settingsProvider.dart'; import 'theming/darkAppTheme.dart'; import 'theming/lightAppTheme.dart'; import 'view/login/login.dart'; +import 'view/pages/more/abiturCalculator/models/abiturCalculatorModel.dart'; import 'widget/placeholderView.dart'; Future main() async { @@ -68,6 +69,8 @@ Future main() async { ChangeNotifierProvider(create: (context) => MessageProps()), ChangeNotifierProvider(create: (context) => HolidaysProps()), + + ChangeNotifierProvider(create: (context) => AbiturCalculatorModel()), ], child: const Main(), ) diff --git a/lib/view/pages/more/abiturCalculator/abiturCalculatorView.dart b/lib/view/pages/more/abiturCalculator/abiturCalculatorView.dart new file mode 100644 index 0000000..5f292a2 --- /dev/null +++ b/lib/view/pages/more/abiturCalculator/abiturCalculatorView.dart @@ -0,0 +1,74 @@ +import 'package:flutter/material.dart'; +import 'package:marianum_mobile/view/pages/more/abiturCalculator/models/abiturCalculatorModel.dart'; +import 'package:marianum_mobile/view/pages/more/abiturCalculator/models/subject.dart'; +import 'package:marianum_mobile/view/pages/more/abiturCalculator/steps/resultStep.dart'; +import 'package:marianum_mobile/view/pages/more/abiturCalculator/steps/selectGkStep.dart'; +import 'package:marianum_mobile/view/pages/more/abiturCalculator/steps/selectLkStep.dart'; +import 'package:marianum_mobile/view/pages/more/abiturCalculator/steps/selectPfStep.dart'; +import 'package:marianum_mobile/view/pages/more/abiturCalculator/steps/welcomeStep.dart'; +import 'package:provider/provider.dart'; + +class AbiturCalculatorView extends StatelessWidget { + const AbiturCalculatorView({super.key}); + + static RichText listSubjects(List subjects) { + return RichText( + textAlign: TextAlign.center, + text: TextSpan( + children: subjects.map((subject) { + return List.from([ + WidgetSpan(child: Icon(subject.icon, size: 15)), + const WidgetSpan(child: SizedBox(width: 3)), + TextSpan(text: subject.displayName), + if(subjects.last != subject) const WidgetSpan(child: SizedBox(width: 10)), + ]); + }).expand((e) => e).toList(), + ), + ); + } + + @override + Widget build(BuildContext context) { + return Consumer(builder: (context, state, child) { + return Scaffold( + appBar: AppBar( + title: const Text("Abitur Notenrechner"), + ), + body: Stepper( + type: StepperType.vertical, + steps: [ + const WelcomeStep(), + SelectLkStep(), + SelectGkStep(), + SelectPfStep(), + const ResultStep(), + ], + currentStep: state.getStep, + onStepTapped: (step) => state.setStep = step, + stepIconBuilder: (stepIndex, stepState) => _stepIconBuilder(context, stepIndex, stepState), + controlsBuilder: _controlsBuilder, + ) + ); + }); + } + + Widget _stepIconBuilder(BuildContext context, int stepIndex, StepState stepState) { + return Consumer(builder: (context, state, child) { + return Container( + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(20), + color: state.getStep == stepIndex + ? Theme.of(context).primaryColor + : Theme.of(context).colorScheme.surface, + ), + child: Center( + child: Text((++stepIndex).toString()), + ), + ); + }); + } + + Widget _controlsBuilder(BuildContext context, details) { + return const Row(children: [SizedBox.shrink()]); + } +} \ 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 new file mode 100644 index 0000000..d1edb27 --- /dev/null +++ b/lib/view/pages/more/abiturCalculator/models/abiturCalculatorModel.dart @@ -0,0 +1,56 @@ +import 'package:flutter/material.dart'; +import 'package:provider/provider.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 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); + notifyListeners(); + } + + int get getStep => _currentStep; + set setStep(int step) { + _currentStep = step; + notifyListeners(); + } + + void reset() { + _currentStep = 0; + _collection = subjects; + notifyListeners(); + } + + AbiturCalculatorModel() { + reset(); + } +} \ No newline at end of file diff --git a/lib/view/pages/more/highEduGraduationCalculator/models/subject.dart b/lib/view/pages/more/abiturCalculator/models/subject.dart similarity index 57% rename from lib/view/pages/more/highEduGraduationCalculator/models/subject.dart rename to lib/view/pages/more/abiturCalculator/models/subject.dart index 881c6ee..2a9efb0 100644 --- a/lib/view/pages/more/highEduGraduationCalculator/models/subject.dart +++ b/lib/view/pages/more/abiturCalculator/models/subject.dart @@ -1,5 +1,5 @@ +import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; -import 'package:marianum_mobile/widget/centeredLeading.dart'; enum SubjectState { none, @@ -13,36 +13,30 @@ class HighEduGraduationConstants { } class SubjectCollection { - List subjects; + List collection; - SubjectCollection(this.subjects); + SubjectCollection(this.collection); } class Subject { String displayName; + IconData icon; bool lkApplicable; SubjectState _subjectState = SubjectState.none; bool isLk() => _subjectState == SubjectState.isLk; bool isGk() => _subjectState == SubjectState.isGk; - bool canLk(List other) => lkApplicable && other.where((s) => s.isLk()).length < HighEduGraduationConstants.maxLks; + bool canLk(List other) => lkApplicable && !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) { _subjectState = isLk ? SubjectState.isLk : SubjectState.none; } + set unsafeGkToggle(bool isGk) { + _subjectState = isGk ? SubjectState.isGk : SubjectState.none; + } - ListTile get asTile => ListTile( - leading: const CenteredLeading(Icon(Icons.subject_outlined)), - title: Text(displayName), - trailing: Checkbox( - value: isGk(), - onChanged: (e) => {}, - ), - ); - - - Subject({required this.displayName, required this.lkApplicable}); + Subject({required this.displayName, required this.icon, required this.lkApplicable}); } \ 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 new file mode 100644 index 0000000..5bdead3 --- /dev/null +++ b/lib/view/pages/more/abiturCalculator/steps/resultStep.dart @@ -0,0 +1,8 @@ +import 'package:flutter/material.dart'; + +class ResultStep extends Step { + const ResultStep() : super( + title: const Text("Ergebnis"), + content: const SizedBox.shrink(), + ); +} \ 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 new file mode 100644 index 0000000..826a0b9 --- /dev/null +++ b/lib/view/pages/more/abiturCalculator/steps/selectGkStep.dart @@ -0,0 +1,29 @@ +import 'package:flutter/material.dart'; +import 'package:marianum_mobile/view/pages/more/abiturCalculator/abiturCalculatorView.dart'; + +import '../models/abiturCalculatorModel.dart'; + +class SelectGkStep extends Step { + SelectGkStep() : super( + title: const Text("Grundkurse"), + content: Builder(builder: (context) { + var gkSubjects = AbiturCalculatorModel.get(context).getSubjects.collection.where((e) => e.isGk()).toList(); + return Column( + children: [ + AbiturCalculatorView.listSubjects(gkSubjects), + TextButton( + onPressed: () { + // showDialog( + // context: context, + // barrierDismissible: false, + // builder: (context) => const SelectGkDialog(), + // ); + }, + child: Text( + "Grundkurse ${gkSubjects.isEmpty ? "auswählen" : "ändern"}"), + ), + ], + ); + }), + ); +} \ 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 new file mode 100644 index 0000000..4e39e5a --- /dev/null +++ b/lib/view/pages/more/abiturCalculator/steps/selectLkStep.dart @@ -0,0 +1,66 @@ +import 'package:flutter/material.dart'; +import 'package:marianum_mobile/widget/providerBridge.dart'; + +import '../../../../../widget/centeredLeading.dart'; +import '../abiturCalculatorView.dart'; +import '../models/abiturCalculatorModel.dart'; + +class SelectLkStep extends Step { + 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(); + return Column( + children: [ + AbiturCalculatorView.listSubjects(lkSubjects), + TextButton( + onPressed: () { + ProviderBridge.toDialog(context, model, (context, value) { + return AlertDialog( + title: const Text("Leistungskurse"), + 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.isLk(), + onChanged: e.isLk() || e.canLk(model.getSubjects.collection) ? (value) { + model.updateSubjects((collection) { + e.unsafeLkToggle = value!; + }); + } : null, + ), + ); + }).toList(), + ), + ), + actions: [ + TextButton( + onPressed: () { + Navigator.of(context).pop(); + }, + child: const Text("Fertig"), + ) + ], + ); + }); + }, + child: Text("Leistungskurse ${lkSubjects.isEmpty ? "auswählen" : "ändern"}"), + ), + ], + ); + }), + ); +} +class SelectLkStepTest extends StatelessWidget { + const SelectLkStepTest({super.key}); + + @override + Widget build(BuildContext context) { + return const Placeholder(); + } +} diff --git a/lib/view/pages/more/abiturCalculator/steps/selectPfStep.dart b/lib/view/pages/more/abiturCalculator/steps/selectPfStep.dart new file mode 100644 index 0000000..3badaa8 --- /dev/null +++ b/lib/view/pages/more/abiturCalculator/steps/selectPfStep.dart @@ -0,0 +1,8 @@ +import 'package:flutter/material.dart'; + +class SelectPfStep extends Step { + const SelectPfStep() : super( + title: const Text("Prüfungsfächer"), + content: const SizedBox.shrink(), + ); +} \ 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 new file mode 100644 index 0000000..b9b859a --- /dev/null +++ b/lib/view/pages/more/abiturCalculator/steps/welcomeStep.dart @@ -0,0 +1,8 @@ +import 'package:flutter/material.dart'; + +class WelcomeStep extends Step { + const WelcomeStep() : super( + title: const Text("Willkommen"), + content: const Text("In den folgenden Schritten werden alle nötigen Informationen zur Ermittlung deiner Abiturzulassung abgefragt.") + ); +} \ No newline at end of file diff --git a/lib/view/pages/more/highEduGraduationCalculator/highEduGraduationCalculator.dart b/lib/view/pages/more/highEduGraduationCalculator/highEduGraduationCalculator.dart deleted file mode 100644 index 1fe8faa..0000000 --- a/lib/view/pages/more/highEduGraduationCalculator/highEduGraduationCalculator.dart +++ /dev/null @@ -1,75 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:marianum_mobile/view/pages/more/highEduGraduationCalculator/models/subject.dart'; -import 'package:marianum_mobile/view/pages/more/highEduGraduationCalculator/selectLkView.dart'; - -class HighEduGraduationCalculator extends StatefulWidget { - const HighEduGraduationCalculator({super.key}); - - @override - State createState() => _HighEduGraduationCalculatorState(); -} - -class _HighEduGraduationCalculatorState extends State { - SubjectCollection allSubjects = SubjectCollection([ - Subject(displayName: "Mathe", lkApplicable: true), - Subject(displayName: "Physik", lkApplicable: true), - Subject(displayName: "Chemie", lkApplicable: true), - Subject(displayName: "Biologie", lkApplicable: true), - Subject(displayName: "Englisch", lkApplicable: true), - Subject(displayName: "Latein", lkApplicable: true), - ]); - - SubjectCollection? lkSubjects; - - int currentStep = 0; - List steps() => [ - Step(title: const Text("Willkommen"), content: Text("test")), - Step(title: const Text("Leistungskurse wählen"), content: lkSubjectsStep()), - const Step(title: Text("Grundkurse wählen"), content: Text("Test")), - const Step(title: Text("Prüfungsfächer wählen"), content: Text("Test")), - const Step(title: Text("Ergebnis auswerten"), content: Text("Test")), - ]; - - Widget lkSubjectsStep() { - return Column( - children: [ - Text(lkSubjects?.subjects.where((e) => e.isLk()).map((e) => e.displayName).join(", ") ?? "Keine Auswahl"), - TextButton( - onPressed: () { - showDialog(context: context, builder: (context) => SelectLkView(all: allSubjects, update: () => setState(() => { }))); - }, - child: const Text("Ändern"), - ), - ], - ); - } - - @override - Widget build(BuildContext context) { - return Scaffold( - appBar: AppBar( - title: const Text("Abitur Notenrechner"), - ), - body: Stepper( - type: StepperType.vertical, - steps: steps(), - currentStep: currentStep, - onStepContinue: () { - setState(() { - currentStep++; - }); - }, - controlsBuilder: (context, details) { - return Row( - children: [ - TextButton( - onPressed: () => details.onStepContinue, - child: const Text("Weiter"), - ) - ], - ); - }, - ) - ); - } -} diff --git a/lib/view/pages/more/highEduGraduationCalculator/selectLkView.dart b/lib/view/pages/more/highEduGraduationCalculator/selectLkView.dart deleted file mode 100644 index 65fbfd7..0000000 --- a/lib/view/pages/more/highEduGraduationCalculator/selectLkView.dart +++ /dev/null @@ -1,47 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:marianum_mobile/view/pages/more/highEduGraduationCalculator/models/subject.dart'; -import 'package:marianum_mobile/widget/centeredLeading.dart'; - -class SelectLkView extends StatefulWidget { - final SubjectCollection all; - final void Function() update; - const SelectLkView({required this.all, required this.update, super.key}); - - @override - State createState() => _SelectLkViewState(); -} - -class _SelectLkViewState extends State { - @override - Widget build(BuildContext context) { - return AlertDialog( - title: const Text("Leistungskurse"), - content: Column( - mainAxisSize: MainAxisSize.min, - children: widget.all.subjects.map((e) { - return ListTile( - leading: const CenteredLeading(Icon(Icons.subject_outlined)), - title: Text(e.displayName), - trailing: Checkbox( - value: e.isLk(), - onChanged: e.isLk() || e.canLk(widget.all.subjects) ? (value) { - setState(() { - e.unsafeLkToggle = value!; - }); - } : null, - ), - ); - }).toList(), - ), - actions: [ - TextButton( - onPressed: () { - widget.update(); - Navigator.of(context).pop(); - }, - child: const Text("Fertig"), - ) - ], - ); - } -} diff --git a/lib/view/pages/overhang.dart b/lib/view/pages/overhang.dart index e52e7e4..8d033f0 100644 --- a/lib/view/pages/overhang.dart +++ b/lib/view/pages/overhang.dart @@ -4,13 +4,13 @@ import 'dart:io'; import 'package:flutter/material.dart'; import 'package:in_app_review/in_app_review.dart'; import 'package:marianum_mobile/extensions/renderNotNull.dart'; -import 'package:marianum_mobile/view/pages/more/highEduGraduationCalculator/highEduGraduationCalculator.dart'; -import 'package:persistent_bottom_nav_bar_v2/persistent-tab-view.dart'; +import 'package:persistent_bottom_nav_bar_v2/persistent_bottom_nav_bar_v2.dart'; import '../../widget/ListItem.dart'; import '../../widget/centeredLeading.dart'; import '../../widget/infoDialog.dart'; import '../settings/settings.dart'; +import 'more/abiturCalculator/abiturCalculatorView.dart'; import 'more/feedback/feedbackDialog.dart'; import 'more/gradeAverages/gradeAverage.dart'; import 'more/holidays/holidays.dart'; @@ -36,7 +36,7 @@ class Overhang extends StatelessWidget { const ListItemNavigator(icon: Icons.newspaper, text: "Marianum Message", target: Message()), const ListItemNavigator(icon: Icons.room, text: "Raumplan", target: Roomplan()), const ListItemNavigator(icon: Icons.calculate, text: "Notendurschnittsrechner", target: GradeAverage()), - const ListItemNavigator(icon: Icons.backup_table_outlined, text: "Abirechner", target: HighEduGraduationCalculator()), + const ListItemNavigator(icon: Icons.school_outlined, text: "Abiturrechner", target: AbiturCalculatorView()), const ListItemNavigator(icon: Icons.calendar_month, text: "Schulferien", target: Holidays()), const Divider(), ListTile( diff --git a/lib/widget/providerBridge.dart b/lib/widget/providerBridge.dart new file mode 100644 index 0000000..6a51311 --- /dev/null +++ b/lib/widget/providerBridge.dart @@ -0,0 +1,19 @@ +import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; + + +class ProviderBridge { + static void toDialog(BuildContext context, T data, Widget Function(BuildContext context, T value) builder) { + showDialog( + context: context, + builder: (context) { + return ChangeNotifierProvider.value( + value: data, + builder: (context, child) { + return Consumer(builder: (context, value, child) => builder(context, value)); + }, + ); + }, + ); + } +}