Added code comments

main
henryhdr 2024-05-10 13:37:09 +02:00
parent 7370acc486
commit 3c1011b83a
7 changed files with 46 additions and 14 deletions

View File

@ -37,23 +37,27 @@ class MyHomePage extends StatefulWidget {
} }
class _MyHomePageState extends State<MyHomePage> { class _MyHomePageState extends State<MyHomePage> {
// Controller und Fokus-Knoten für die Eingabefelder
final TextEditingController _initialCapitalController = TextEditingController(); final TextEditingController _initialCapitalController = TextEditingController();
final TextEditingController _monthlySavingsRateController = TextEditingController(); final TextEditingController _monthlySavingsRateController = TextEditingController();
final TextEditingController _interestRateController = TextEditingController(); final TextEditingController _interestRateController = TextEditingController();
final TextEditingController _timeController = TextEditingController(); final TextEditingController _timeController = TextEditingController();
bool _isInitialCapitalEntered = false;
bool _isMonthlySavingsRateEntered = false;
bool _isInterestRateEntered = false;
bool _isTimeEntered = false;
final FocusNode _initialCapitalFocusNode = FocusNode(); final FocusNode _initialCapitalFocusNode = FocusNode();
final FocusNode _monthlySavingsRateFocusNode = FocusNode(); final FocusNode _monthlySavingsRateFocusNode = FocusNode();
final FocusNode _interestRateFocusNode = FocusNode(); final FocusNode _interestRateFocusNode = FocusNode();
final FocusNode _timeFocusNode = FocusNode(); final FocusNode _timeFocusNode = FocusNode();
// Zustandsvariablen für die Validierung der Eingaben
bool _isInitialCapitalEntered = false;
bool _isMonthlySavingsRateEntered = false;
bool _isInterestRateEntered = false;
bool _isTimeEntered = false;
@override @override
void initState() { void initState() {
super.initState(); super.initState();
// Listener für die Eingabefelder, um die Validierung durchzuführen und Standardwerte wiederherzustellen
_initialCapitalController.addListener(() { _initialCapitalController.addListener(() {
setState(() { setState(() {
_isInitialCapitalEntered = _initialCapitalController.text.isNotEmpty && _isInitialCapitalEntered = _initialCapitalController.text.isNotEmpty &&
@ -86,6 +90,7 @@ class _MyHomePageState extends State<MyHomePage> {
}); });
}); });
// Listener für die Fokus-Knoten, um die Eingabe zu runden, wenn der Fokus verloren geht
_initialCapitalFocusNode.addListener(() { _initialCapitalFocusNode.addListener(() {
if (!_initialCapitalFocusNode.hasFocus) { if (!_initialCapitalFocusNode.hasFocus) {
roundToInteger(_initialCapitalController); roundToInteger(_initialCapitalController);
@ -110,10 +115,11 @@ class _MyHomePageState extends State<MyHomePage> {
} }
}); });
_initialCapitalController.text = '1000'; // Beispielwert für Anfangskapital // Setzen von Beispielwerten für die Eingabefelder
_monthlySavingsRateController.text = '50'; // Beispielwert für monatliche Sparrate _initialCapitalController.text = '1000';
_interestRateController.text = '5'; // Beispielwert für jährlichen Zinssatz _monthlySavingsRateController.text = '50';
_timeController.text = '10'; // Beispielwert für Anlagezeitraum _interestRateController.text = '5';
_timeController.text = '10';
} }
@ -122,12 +128,13 @@ class _MyHomePageState extends State<MyHomePage> {
double _interestRate = 0.0; // Jährlicher Zinssatz double _interestRate = 0.0; // Jährlicher Zinssatz
double _time = 0.0; // Anlagezeitraum in Jahren double _time = 0.0; // Anlagezeitraum in Jahren
double _investedMoney = 0.0; // Investiertes Geld ohne Zinsen double _investedMoney = 0.0; // Investiertes Geld ohne Zinsen
List<double> _investedMoneyList = []; // Investiertes Geld ohne Zinsen (pro Jahr) final List<double> _investedMoneyList = []; // Investiertes Geld ohne Zinsen (pro Jahr)
PayoutInterval _payoutInterval = PayoutInterval.yearly; // Standardwert für das Ausschüttungsintervall PayoutInterval _payoutInterval = PayoutInterval.yearly; // Standardwert für das Ausschüttungsintervall
double _compoundInterest = 0.0; // Investiertes Geld mit Zinsen double _compoundInterest = 0.0; // Investiertes Geld mit Zinsen
List<double> _compoundInterestList = []; // Investiertes Geld mit Zinsen (pro Jahr) final List<double> _compoundInterestList = []; // Investiertes Geld mit Zinsen (pro Jahr)
bool _calculationPerformed = false; bool _calculationPerformed = false;
// Methoden zum Festlegen der Werte aus den Eingabefeldern
void setInitialCapital() { void setInitialCapital() {
setState(() { setState(() {
_initialCapital = double.parse(_initialCapitalController.text); _initialCapital = double.parse(_initialCapitalController.text);
@ -152,6 +159,7 @@ class _MyHomePageState extends State<MyHomePage> {
}); });
} }
// Methode zum Berechnen des investierten Geldes
void _calculateInvestedMoney() { void _calculateInvestedMoney() {
setState(() { setState(() {
_investedMoneyList.clear(); _investedMoneyList.clear();
@ -165,6 +173,7 @@ class _MyHomePageState extends State<MyHomePage> {
}); });
} }
// Methode zum Berechnen der Zinsen
void _calculateCompoundInterest() { void _calculateCompoundInterest() {
setState(() { setState(() {
_compoundInterestList.clear(); _compoundInterestList.clear();

View File

@ -1,5 +1,6 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
// Rundet den Wert im Textfeld-Controller auf die nächste ganze Zahl
void roundToInteger(TextEditingController controller) { void roundToInteger(TextEditingController controller) {
double? parsedValue = double.tryParse(controller.text.replaceAll(',', '.')); double? parsedValue = double.tryParse(controller.text.replaceAll(',', '.'));
if (parsedValue != null) { if (parsedValue != null) {
@ -8,10 +9,12 @@ void roundToInteger(TextEditingController controller) {
} }
} }
// Überprüft, ob der gegebene Wert eine numerische Darstellung ist
bool isNumeric(String value) { bool isNumeric(String value) {
return double.tryParse(value.replaceAll(',', '.')) != null; return double.tryParse(value.replaceAll(',', '.')) != null; // Wert in einen double umwandeln
} }
// Setzt den Standardwert 0 für den Controller, wenn das Feld leer ist
void restoreDefaultValuesIfEmpty(TextEditingController controller) { void restoreDefaultValuesIfEmpty(TextEditingController controller) {
if (controller.text.isEmpty) { if (controller.text.isEmpty) {
controller.text = '0'; controller.text = '0';

View File

@ -1,6 +1,7 @@
import 'package:flutter/cupertino.dart'; import 'package:flutter/cupertino.dart';
import 'package:syncfusion_flutter_charts/charts.dart'; import 'package:syncfusion_flutter_charts/charts.dart';
// Widget für ein gestapeltes Säulendiagramm
class StackedColumnChart extends StatelessWidget { class StackedColumnChart extends StatelessWidget {
final List<double> lowerValues; final List<double> lowerValues;
final List<double> upperValues; final List<double> upperValues;
@ -21,12 +22,14 @@ class StackedColumnChart extends StatelessWidget {
title: AxisTitle(text: 'Euro'), title: AxisTitle(text: 'Euro'),
), ),
series: <CartesianSeries>[ series: <CartesianSeries>[
// Untere Teil der Säule
StackedColumnSeries<SalesData, int>( StackedColumnSeries<SalesData, int>(
dataSource: _getLowerChartData(), dataSource: _getLowerChartData(),
xValueMapper: (SalesData sales, _) => sales.year, xValueMapper: (SalesData sales, _) => sales.year,
yValueMapper: (SalesData sales, _) => sales.value, yValueMapper: (SalesData sales, _) => sales.value,
color: CupertinoColors.systemRed.highContrastColor, color: CupertinoColors.systemRed.highContrastColor,
), ),
// Obere Teil der Säule
StackedColumnSeries<SalesData, int>( StackedColumnSeries<SalesData, int>(
dataSource: _getUpperChartData(), dataSource: _getUpperChartData(),
xValueMapper: (SalesData sales, _) => sales.year, xValueMapper: (SalesData sales, _) => sales.year,
@ -37,6 +40,7 @@ class StackedColumnChart extends StatelessWidget {
); );
} }
// Methode zum Erstellen der Daten für den unteren Teil der Säule (Investiertes Geld)
List<SalesData> _getLowerChartData() { List<SalesData> _getLowerChartData() {
List<SalesData> chartData = []; List<SalesData> chartData = [];
for (int i = 0; i < lowerValues.length; i++) { for (int i = 0; i < lowerValues.length; i++) {
@ -44,7 +48,7 @@ class StackedColumnChart extends StatelessWidget {
} }
return chartData; return chartData;
} }
// Methode zum Erstellen der Daten für den oberen Teil der Säule (Investiertes Geld mit Zinsen)
List<SalesData> _getUpperChartData() { List<SalesData> _getUpperChartData() {
List<SalesData> chartData = []; List<SalesData> chartData = [];
for (int i = 0; i < upperValues.length; i++) { for (int i = 0; i < upperValues.length; i++) {

View File

@ -1,6 +1,7 @@
import 'package:flutter/cupertino.dart'; import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
// Widget für eine erweiterbare Box
class ExpandableBox extends StatefulWidget { class ExpandableBox extends StatefulWidget {
final String headerText; final String headerText;
final Widget expandedContent; final Widget expandedContent;
@ -19,6 +20,7 @@ class _ExpandableBoxState extends State<ExpandableBox> {
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Column( return Column(
children: [ children: [
// GestureDetector zum Erfassen von Klicks zum Erweitern oder Verkleinern der Box
GestureDetector( GestureDetector(
onTap: () { onTap: () {
setState(() { setState(() {

View File

@ -1,6 +1,7 @@
import 'package:flutter/cupertino.dart'; import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
// Funktion zum Erstellen eines Eingabe-Widgets
Widget buildInputWidget(String label, TextEditingController controller, FocusNode focusNode, bool isValid, String suffixText, String tooltipText) { Widget buildInputWidget(String label, TextEditingController controller, FocusNode focusNode, bool isValid, String suffixText, String tooltipText) {
return Column( return Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
@ -8,6 +9,7 @@ Widget buildInputWidget(String label, TextEditingController controller, FocusNod
Row( Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween, mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [ children: [
// Zeile für das Label und den Tooltip
Row( Row(
children: [ children: [
Row( Row(
@ -42,6 +44,7 @@ Widget buildInputWidget(String label, TextEditingController controller, FocusNod
], ],
), ),
const SizedBox(height: 5), const SizedBox(height: 5),
// Textfeld für die Eingabe
CupertinoTextField( CupertinoTextField(
controller: controller, controller: controller,
focusNode: focusNode, focusNode: focusNode,

View File

@ -3,6 +3,7 @@ import 'package:flutter/material.dart';
import 'package:flutter_application_1/enums.dart'; import 'package:flutter_application_1/enums.dart';
import 'package:flutter_application_1/translations.dart'; import 'package:flutter_application_1/translations.dart';
// Widget zur Auswahl des Ausschüttungsintervalls
class IntervalWidget extends StatefulWidget { class IntervalWidget extends StatefulWidget {
final String selectedInterval; final String selectedInterval;
final Function(String) onChanged; final Function(String) onChanged;
@ -22,6 +23,7 @@ class _IntervalWidgetState extends State<IntervalWidget> {
return Column( return Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
// Überschrift für das Dropdown-Menü
const Row( const Row(
children: [ children: [
Text( Text(
@ -38,6 +40,7 @@ class _IntervalWidgetState extends State<IntervalWidget> {
), ),
] ]
), ),
// Dropdown-Menü
CupertinoTextField( CupertinoTextField(
placeholder: 'Ausschüttungsintervall auswählen', placeholder: 'Ausschüttungsintervall auswählen',
readOnly: true, readOnly: true,
@ -49,6 +52,7 @@ class _IntervalWidgetState extends State<IntervalWidget> {
return Column( return Column(
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,
children: [ children: [
// Liste von Auswahlmöglichkeiten
Padding( Padding(
padding: const EdgeInsets.symmetric(vertical: 8.0), padding: const EdgeInsets.symmetric(vertical: 8.0),
child: ListTile( child: ListTile(
@ -61,6 +65,7 @@ class _IntervalWidgetState extends State<IntervalWidget> {
hoverColor: Colors.transparent, hoverColor: Colors.transparent,
trailing: widget.selectedInterval == translateInterval(PayoutInterval.yearly) ? const Icon(CupertinoIcons.checkmark_alt) : null, trailing: widget.selectedInterval == translateInterval(PayoutInterval.yearly) ? const Icon(CupertinoIcons.checkmark_alt) : null,
onTap: () { onTap: () {
// Auswahl des jährlichen Intervalls und Schließen des Bottom Sheets
widget.onChanged(translateInterval(PayoutInterval.yearly)); widget.onChanged(translateInterval(PayoutInterval.yearly));
Navigator.pop(context); Navigator.pop(context);
}, },
@ -78,6 +83,7 @@ class _IntervalWidgetState extends State<IntervalWidget> {
hoverColor: Colors.transparent, hoverColor: Colors.transparent,
trailing: widget.selectedInterval == translateInterval(PayoutInterval.monthly) ? const Icon(CupertinoIcons.checkmark_alt) : null, trailing: widget.selectedInterval == translateInterval(PayoutInterval.monthly) ? const Icon(CupertinoIcons.checkmark_alt) : null,
onTap: () { onTap: () {
// Auswahl des monatlichen Intervalls und Schließen des Bottom Sheets
widget.onChanged(translateInterval(PayoutInterval.monthly)); widget.onChanged(translateInterval(PayoutInterval.monthly));
Navigator.pop(context); Navigator.pop(context);
}, },

View File

@ -4,7 +4,9 @@ import 'package:flutter_application_1/translations.dart';
import 'package:flutter_application_1/widgets/expandable_widget.dart'; import 'package:flutter_application_1/widgets/expandable_widget.dart';
import 'package:flutter_application_1/widgets/chart_widget.dart'; import 'package:flutter_application_1/widgets/chart_widget.dart';
// Erstellt das Widget für das Ergebnis der Berechnungen
Widget buildResultWidget(String compoundInterest, String investedMoney, String time, String monthlySavingsRate, String interestRate, PayoutInterval payoutInterval, List<double> investedMoneyList, List<double> compoundInterestList) { Widget buildResultWidget(String compoundInterest, String investedMoney, String time, String monthlySavingsRate, String interestRate, PayoutInterval payoutInterval, List<double> investedMoneyList, List<double> compoundInterestList) {
// Liste von Meilensteinen mit Werten, Bildern und Texten.
List<Map<String, dynamic>> milestoneList = [ List<Map<String, dynamic>> milestoneList = [
{'value': 1329, 'image': 'iphone-15-pro-model.png', 'text': 'iPhone 15 Pro Max\nPreis: 1329€', 'size': 20}, {'value': 1329, 'image': 'iphone-15-pro-model.png', 'text': 'iPhone 15 Pro Max\nPreis: 1329€', 'size': 20},
{'value': 3071, 'image': 'flyer-gotour6-model.png', 'text': 'Flyer Gotour6 3.40\nPreis: 3071€', 'size': 70}, {'value': 3071, 'image': 'flyer-gotour6-model.png', 'text': 'Flyer Gotour6 3.40\nPreis: 3071€', 'size': 70},
@ -60,12 +62,14 @@ Widget _buildResultRow(String label, String value) {
); );
} }
// Erstellt die Meilenstein-Timeline.
Widget buildMilestoneTimeline(List<Map<String, dynamic>> milestones, double totalInterest) { Widget buildMilestoneTimeline(List<Map<String, dynamic>> milestones, double totalInterest) {
return SizedBox( return SizedBox(
child: Center( child: Center(
child: Column( child: Column(
mainAxisAlignment: MainAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center,
children: List.generate(milestones.length, (index) { children: List.generate(milestones.length, (index) {
// Werte aus dem Meilenstein-Objekt extrahieren
double milestoneValue = milestones[index]['value']; double milestoneValue = milestones[index]['value'];
String milestoneImage = milestones[index]['image']; String milestoneImage = milestones[index]['image'];
String milestoneText = milestones[index]['text']; String milestoneText = milestones[index]['text'];
@ -73,7 +77,7 @@ Widget buildMilestoneTimeline(List<Map<String, dynamic>> milestones, double tota
bool milestoneReached = totalInterest >= milestoneValue; bool milestoneReached = totalInterest >= milestoneValue;
return Column( return Column(
children: [ children: [
if (index < milestones.length && index > 0) if (index < milestones.length && index > 0) // Zeigt eine vertikale Linie an zwischen den Meilensteinen
Container( Container(
height: 50, height: 50,
width: 2, width: 2,
@ -88,7 +92,7 @@ Widget buildMilestoneTimeline(List<Map<String, dynamic>> milestones, double tota
width: milestoneSize, width: milestoneSize,
fit: BoxFit.cover, fit: BoxFit.cover,
), ),
const SizedBox(height: 5), // Abstand zwischen Bild und Text const SizedBox(height: 5),
Text( Text(
milestoneText, milestoneText,
textAlign: TextAlign.center, textAlign: TextAlign.center,
@ -99,6 +103,7 @@ Widget buildMilestoneTimeline(List<Map<String, dynamic>> milestones, double tota
], ],
), ),
), ),
// Zeigt ein Häkchen oder einen Kreis je nach Erreichen des Meilensteins an
Padding( Padding(
padding: const EdgeInsets.symmetric(vertical: 4.0), padding: const EdgeInsets.symmetric(vertical: 4.0),
child: Icon( child: Icon(