Added code comments
parent
7370acc486
commit
3c1011b83a
|
@ -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();
|
||||||
|
|
|
@ -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';
|
||||||
|
|
|
@ -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++) {
|
||||||
|
|
|
@ -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(() {
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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);
|
||||||
},
|
},
|
||||||
|
|
|
@ -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(
|
||||||
|
|
Loading…
Reference in New Issue