Changed features

main
henryhdr 2024-05-24 14:04:26 +02:00
parent b791a4b69f
commit 473db9335e
13 changed files with 295 additions and 242 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 300 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 MiB

View File

@ -0,0 +1,35 @@
import 'package:flutter_application_1/enums.dart';
// Berechnet das investierte Geld über eine bestimmte Zeit
double calculateInvestedMoney(double initialCapital, double monthlySavingsRate, double time, List<double> investedMoneyList) {
double investedMoney = initialCapital;
investedMoneyList.clear();
for (int i = 0; i < time; i++) {
investedMoney += monthlySavingsRate * 12; // Jährliche Sparrate hinzufügen
investedMoney = investedMoney.roundToDouble();
investedMoneyList.add(investedMoney); // Investierten Betrag zur Liste hinzufügen
}
return investedMoney;
}
// Berechnet den Zinseszins über eine bestimmte Zeit.
double calculateCompoundInterest(double initialCapital, double monthlySavingsRate, double interestRate, double time, PayoutInterval payoutInterval, List<double> investedMoneyList, List<double> compoundInterestList) {
double compoundInterest = initialCapital;
compoundInterestList.clear();
if (payoutInterval == PayoutInterval.yearly) { // Berechnung für jährliche Auszahlung
for (int i = 0; i < time; i++) {
compoundInterest += compoundInterest * (interestRate / 100) + monthlySavingsRate * 12; // Zinsen und jährliche Sparrate hinzufügen
compoundInterest = compoundInterest.roundToDouble();
compoundInterestList.add(compoundInterest - investedMoneyList[i]); // Zinseszins zur Liste hinzufügen
}
} else { // Berechnung für monatliche Auszahlung
for (int i = 0; i < time; i++) {
for (int j = 0; j < 12; j++) {
compoundInterest += compoundInterest * ((interestRate / 100) / 12) + monthlySavingsRate; // Monatliche Zinsen und Sparrate hinzufügen
compoundInterest = compoundInterest.roundToDouble();
}
compoundInterestList.add(compoundInterest - investedMoneyList[i]); // Zinseszins zur Liste hinzufügen
}
}
return compoundInterest; // Gesamtkapital nach Zinseszinsberechnung zurückgeben
}

View File

@ -1,5 +1,6 @@
import 'package:flutter/material.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter_application_1/calculator.dart';
import 'package:flutter_application_1/enums.dart';
import 'package:flutter_application_1/translations.dart';
import 'package:flutter_application_1/utils.dart';
@ -122,17 +123,15 @@ class _MyHomePageState extends State<MyHomePage> {
_timeController.text = '10';
}
double _initialCapital = 0.0; // Anfangskapital
double _monthlySavingsRate = 0.0; // Monatliche Sparrate
double _interestRate = 0.0; // Jährlicher Zinssatz
double _time = 0.0; // Anlagezeitraum in Jahren
double _investedMoney = 0.0; // Investiertes Geld ohne Zinsen
final List<double> _investedMoneyList = []; // Investiertes Geld ohne Zinsen (pro Jahr)
PayoutInterval _payoutInterval = PayoutInterval.yearly; // Standardwert für das Ausschüttungsintervall
double _compoundInterest = 0.0; // Investiertes Geld mit Zinsen
final List<double> _compoundInterestList = []; // Investiertes Geld mit Zinsen (pro Jahr)
bool _calculationPerformed = false;
double _initialCapital = 0.0; // Das anfängliche Kapital
double _monthlySavingsRate = 0.0; // Der monatliche Sparbetrag
double _interestRate = 0.0; // Der jährliche Zinssatz
double _time = 0.0; // Der Anlagezeitraum in Jahren
double _investedMoney = 0.0; // Das investierte Geld
final List<double> _investedMoneyList = []; // Liste, die das investierte Geld pro Jahr speichert
PayoutInterval _payoutInterval = PayoutInterval.yearly; // Das Auszahlungsintervall (jährlich oder monatlich)
double _compoundInterest = 0.0; // Der Zinseszins
final List<double> _compoundInterestList = []; // Liste, die den Zinseszins pro Jahr speichert
// Methoden zum Festlegen der Werte aus den Eingabefeldern
void setInitialCapital() {
@ -159,44 +158,7 @@ class _MyHomePageState extends State<MyHomePage> {
});
}
// Methode zum Berechnen des investierten Geldes
void _calculateInvestedMoney() {
setState(() {
_investedMoneyList.clear();
_investedMoney = _initialCapital;
for (int i = 0; i < _time; i++) {
_investedMoney += _monthlySavingsRate * 12;
_investedMoney = _investedMoney.roundToDouble();
_investedMoneyList.add(_investedMoney);
}
_calculationPerformed = true;
});
}
// Methode zum Berechnen der Zinsen
void _calculateCompoundInterest() {
setState(() {
_compoundInterestList.clear();
_compoundInterest = _initialCapital;
if(_payoutInterval == PayoutInterval.yearly){
for(int i = 0; i < _time; i++){
_compoundInterest += _compoundInterest * (_interestRate / 100) + _monthlySavingsRate * 12;
_compoundInterest = _compoundInterest.roundToDouble();
_compoundInterestList.add(_compoundInterest - _investedMoneyList[i]);
}
}
else{
for(int i = 0; i < _time; i++){
for(int j = 0; j < 12; j++){
_compoundInterest += _compoundInterest * ((_interestRate / 100) / 12) + _monthlySavingsRate;
_compoundInterest = _compoundInterest.roundToDouble();
}
_compoundInterestList.add(_compoundInterest - _investedMoneyList[i]);
}
}
_calculationPerformed = true;
});
}
bool calculationPerformed = false;
@override
Widget build(BuildContext context) {
@ -227,12 +189,18 @@ class _MyHomePageState extends State<MyHomePage> {
setMonthlySavingsRate();
setInterestRate();
setTime();
_calculateInvestedMoney();
_calculateCompoundInterest();
_investedMoney = calculateInvestedMoney(_initialCapital, _monthlySavingsRate, _time, _investedMoneyList);
_compoundInterest = calculateCompoundInterest(_initialCapital, _monthlySavingsRate, _interestRate, _time, _payoutInterval, _investedMoneyList, _compoundInterestList);
calculationPerformed = true;
},
style: ButtonStyle(
backgroundColor: MaterialStateProperty.all<Color>(CupertinoColors.black),
foregroundColor: MaterialStateProperty.all<Color>(CupertinoColors.white),
shape: MaterialStateProperty.all<RoundedRectangleBorder>(
RoundedRectangleBorder(
borderRadius: BorderRadius.circular(5),
),
),
),
child: const Text(
'Berechnen',
@ -242,8 +210,8 @@ class _MyHomePageState extends State<MyHomePage> {
),
),
const SizedBox(height: 20),
if(_calculationPerformed)
buildResultWidget('$_compoundInterest', '$_investedMoney', '$_time', '$_monthlySavingsRate', '$_interestRate', _payoutInterval, _investedMoneyList, _compoundInterestList),
if (calculationPerformed)
buildResultWidget(context, '$_compoundInterest', '$_investedMoney', '$_time', '$_monthlySavingsRate', '$_interestRate', _payoutInterval, _investedMoneyList, _compoundInterestList),
],
),
)

View File

@ -1,10 +1,10 @@
import 'package:flutter/cupertino.dart';
import 'package:syncfusion_flutter_charts/charts.dart';
// Widget für ein gestapeltes Säulendiagramm
// Widget zur Erstellung eines gestapelten Säulendiagramms
class StackedColumnChart extends StatelessWidget {
final List<double> lowerValues;
final List<double> upperValues;
final List<double> lowerValues; // Liste der unteren Werte für das Diagramm
final List<double> upperValues; // Liste der oberen Werte für das Diagramm
const StackedColumnChart({
super.key,
@ -16,8 +16,8 @@ class StackedColumnChart extends StatelessWidget {
Widget build(BuildContext context) {
return SfCartesianChart(
legend: const Legend(
isVisible: true, // Legende anzeigen
position: LegendPosition.top, // Legende unterhalb des Diagramms platzieren
isVisible: true,
position: LegendPosition.top,
),
primaryXAxis: const CategoryAxis(
title: AxisTitle(text: 'Jahr'),
@ -26,24 +26,24 @@ class StackedColumnChart extends StatelessWidget {
title: AxisTitle(text: 'Euro'),
),
series: <CartesianSeries>[
// Untere Teil der Säule
// Serie für die Einzahlungen (untere Werte)
StackedColumnSeries<SalesData, int>(
dataSource: _getLowerChartData(),
xValueMapper: (SalesData sales, _) => sales.year,
yValueMapper: (SalesData sales, _) => sales.value,
name: 'Einzahlungen',
color: CupertinoColors.systemRed.highContrastColor,
color: CupertinoColors.systemGrey.darkHighContrastColor,
),
// Obere Teil der Säule
// Serie für die Zinsen (obere Werte)
StackedColumnSeries<SalesData, int>(
dataSource: _getUpperChartData(),
xValueMapper: (SalesData sales, _) => sales.year,
yValueMapper: (SalesData sales, _) => sales.value,
name: 'Zinsen',
color: CupertinoColors.systemBlue.highContrastColor,
color: CupertinoColors.systemGreen.highContrastColor,
),
],
// Trackball für Hover-Interaktion
// Konfiguration für die Interaktivität des Diagramms
trackballBehavior: TrackballBehavior(
enable: true,
tooltipSettings: const InteractiveTooltip(enable: true),
@ -53,7 +53,7 @@ class StackedColumnChart extends StatelessWidget {
);
}
// Methode zum Erstellen der Daten für den unteren Teil der Säule (Investiertes Geld)
// Methode zur Erstellung der Daten für die untere Serie (Einzahlungen)
List<SalesData> _getLowerChartData() {
List<SalesData> chartData = [];
for (int i = 0; i < lowerValues.length; i++) {
@ -61,7 +61,8 @@ class StackedColumnChart extends StatelessWidget {
}
return chartData;
}
// Methode zum Erstellen der Daten für den oberen Teil der Säule (Investiertes Geld mit Zinsen)
// Methode zur Erstellung der Daten für die obere Serie (Zinsen)
List<SalesData> _getUpperChartData() {
List<SalesData> chartData = [];
for (int i = 0; i < upperValues.length; i++) {
@ -71,6 +72,7 @@ class StackedColumnChart extends StatelessWidget {
}
}
// Klasse zur Modellierung der Datenpunkte im Diagramm
class SalesData {
final int year;
final double value;

View File

@ -0,0 +1,37 @@
import 'package:flutter/material.dart';
class CustomImageButton extends StatelessWidget {
final VoidCallback onPressed;
final Widget child;
final String backgroundImage;
const CustomImageButton({
super.key,
required this.onPressed,
required this.child,
required this.backgroundImage,
});
@override
Widget build(BuildContext context) {
return Material(
color: Colors.transparent,
child: InkWell(
onTap: onPressed,
child: Container(
height: 150,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(5),
image: DecorationImage(
image: AssetImage(backgroundImage),
fit: BoxFit.cover,
),
),
child: Center(
child: child,
),
),
),
);
}
}

View File

@ -1,72 +0,0 @@
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
// Widget für eine erweiterbare Box
class ExpandableBox extends StatefulWidget {
final String headerText;
final Widget expandedContent;
const ExpandableBox({super.key, required this.headerText, required this.expandedContent});
@override
// ignore: library_private_types_in_public_api
_ExpandableBoxState createState() => _ExpandableBoxState();
}
class _ExpandableBoxState extends State<ExpandableBox> {
bool _isExpanded = false;
@override
Widget build(BuildContext context) {
return Column(
children: [
// GestureDetector zum Erfassen von Klicks zum Erweitern oder Verkleinern der Box
GestureDetector(
onTap: () {
setState(() {
_isExpanded = !_isExpanded;
});
},
child: Container(
decoration: BoxDecoration(
color: CupertinoColors.extraLightBackgroundGray,
borderRadius: _isExpanded ? const BorderRadius.only(topLeft: Radius.circular(5), topRight: Radius.circular(5),) : BorderRadius.circular(5),
),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Padding(
padding: const EdgeInsets.symmetric(horizontal: 16.0),
child: Text(
widget.headerText,
style: const TextStyle(
fontWeight: FontWeight.bold
),
),
),
Icon(
_isExpanded ? Icons.keyboard_arrow_up : Icons.keyboard_arrow_down,
size: 30,
),
],
),
),
),
if (_isExpanded)
Container(
decoration: const BoxDecoration(
color: CupertinoColors.extraLightBackgroundGray,
borderRadius: BorderRadius.only(
bottomLeft: Radius.circular(5),
bottomRight: Radius.circular(5),
),
),
child: Padding(
padding: const EdgeInsets.all(20), // Hier kannst du den gewünschten Padding-Wert festlegen
child: widget.expandedContent,
),
)
],
);
}
}

View File

@ -1,7 +1,7 @@
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
// Funktion zum Erstellen eines Eingabe-Widgets
// Erstellt ein Widget für die Eingabe mit einem Label, einem Texteingabefeld, einer Validierungsanzeige und einem Tooltip
Widget buildInputWidget(String label, TextEditingController controller, FocusNode focusNode, bool isValid, String suffixText, String tooltipText) {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
@ -9,11 +9,11 @@ Widget buildInputWidget(String label, TextEditingController controller, FocusNod
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
// Zeile für das Label und den Tooltip
Row(
children: [
Row(
children: [
// Label für das Eingabefeld
Text(
label,
style: const TextStyle(
@ -22,6 +22,7 @@ Widget buildInputWidget(String label, TextEditingController controller, FocusNod
),
),
const SizedBox(width: 5),
// Tooltip-Icon mit Erklärungstext
Tooltip(
message: tooltipText,
triggerMode: TooltipTriggerMode.tap,
@ -39,6 +40,7 @@ Widget buildInputWidget(String label, TextEditingController controller, FocusNod
),
],
),
// Icon zur Anzeige der Validierung (grün für gültig, rot für ungültig)
isValid
? const Icon(
CupertinoIcons.check_mark_circled_solid,
@ -53,7 +55,7 @@ Widget buildInputWidget(String label, TextEditingController controller, FocusNod
],
),
const SizedBox(height: 5),
// Textfeld für die Eingabe
// Texteingabefeld mit Suffix-Text
CupertinoTextField(
controller: controller,
focusNode: focusNode,

View File

@ -3,27 +3,28 @@ import 'package:flutter/material.dart';
import 'package:flutter_application_1/enums.dart';
import 'package:flutter_application_1/translations.dart';
// Widget zur Auswahl des Ausschüttungsintervalls
class IntervalWidget extends StatefulWidget {
final String selectedInterval;
final Function(String) onChanged;
const IntervalWidget({super.key, required this.selectedInterval, required this.onChanged});
const IntervalWidget({
super.key,
required this.selectedInterval,
required this.onChanged
});
@override
// ignore: library_private_types_in_public_api
_IntervalWidgetState createState() => _IntervalWidgetState();
IntervalWidgetState createState() => IntervalWidgetState();
}
class _IntervalWidgetState extends State<IntervalWidget> {
bool isExpanded = false;
class IntervalWidgetState extends State<IntervalWidget> {
bool isExpanded = false; // Zustand, ob das Intervall-Auswahlfenster erweitert ist
@override
Widget build(BuildContext context) {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
// Überschrift für das Dropdown-Menü
const Row(
children: [
Text(
@ -34,6 +35,7 @@ class _IntervalWidgetState extends State<IntervalWidget> {
),
),
SizedBox(width: 5),
// Tooltip mit Erklärung zum Ausschüttungsintervall
Tooltip(
message: 'Das Ausschüttungsintervall bezieht sich darauf, wie oft die Erträge aus Ihrer Investition ausgeschüttet werden.',
triggerMode: TooltipTriggerMode.tap,
@ -49,19 +51,19 @@ class _IntervalWidgetState extends State<IntervalWidget> {
),
]
),
// Dropdown-Menü
CupertinoTextField(
placeholder: 'Ausschüttungsintervall auswählen',
readOnly: true,
onTap: () {
// Öffnet das ModalBottomSheet zur Auswahl des Ausschüttungsintervalls
showModalBottomSheet(
context: context,
backgroundColor: CupertinoColors.white,
backgroundColor: CupertinoColors.black,
builder: (BuildContext context) {
return Column(
mainAxisSize: MainAxisSize.min,
children: [
// Liste von Auswahlmöglichkeiten
// ListTile für jährliches Ausschüttungsintervall
Padding(
padding: const EdgeInsets.symmetric(vertical: 8.0),
child: ListTile(
@ -69,17 +71,17 @@ class _IntervalWidgetState extends State<IntervalWidget> {
translateInterval(PayoutInterval.yearly),
style: const TextStyle(
fontWeight: FontWeight.bold,
color: CupertinoColors.white,
),
),
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, color: CupertinoColors.white,) : null,
onTap: () {
// Auswahl des jährlichen Intervalls und Schließen des Bottom Sheets
widget.onChanged(translateInterval(PayoutInterval.yearly));
Navigator.pop(context);
},
),
),
// ListTile für monatliches Ausschüttungsintervall
Padding(
padding: const EdgeInsets.symmetric(vertical: 8.0),
child: ListTile(
@ -87,12 +89,11 @@ class _IntervalWidgetState extends State<IntervalWidget> {
translateInterval(PayoutInterval.monthly),
style: const TextStyle(
fontWeight: FontWeight.bold,
color: CupertinoColors.white,
),
),
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, color: CupertinoColors.white,) : null,
onTap: () {
// Auswahl des monatlichen Intervalls und Schließen des Bottom Sheets
widget.onChanged(translateInterval(PayoutInterval.monthly));
Navigator.pop(context);
},
@ -103,18 +104,19 @@ class _IntervalWidgetState extends State<IntervalWidget> {
},
).then((value) {
setState(() {
isExpanded = false;
isExpanded = false; // Setzt den Zustand auf nicht erweitert zurück, wenn das Modal geschlossen wird
});
});
setState(() {
isExpanded = true;
isExpanded = true; // Setzt den Zustand auf erweitert
});
},
// Suffix-Icon, das den Zustand anzeigt (erweitert oder nicht)
suffix: Padding(
padding: const EdgeInsets.symmetric(horizontal: 5.0),
child: Icon(isExpanded ? Icons.keyboard_arrow_up : Icons.keyboard_arrow_down),
),
controller: TextEditingController(text: widget.selectedInterval),
controller: TextEditingController(text: widget.selectedInterval), // Setzt den Text des Textfeldes auf das ausgewählte Intervall
decoration: BoxDecoration(
color: CupertinoColors.extraLightBackgroundGray,
borderRadius: BorderRadius.circular(5),

View File

@ -0,0 +1,52 @@
// Erstellt eine Zeitleiste für Meilensteine
import 'package:flutter/cupertino.dart';
Widget buildMilestoneTimeline(List<Map<String, dynamic>> milestones, double totalInterest) {
return SizedBox(
child: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: List.generate(milestones.length, (index) {
double milestoneValue = milestones[index]['value'];
String milestoneEmoji = milestones[index]['emoji'];
String milestoneText = milestones[index]['text'];
bool milestoneReached = totalInterest >= milestoneValue; // Überprüfen, ob Meilenstein erreicht wurde
return Column(
children: [
if (index > 0)
Container(
height: 25,
width: 2,
color: milestoneReached ? CupertinoColors.systemGreen : CupertinoColors.black, // Linie zwischen Meilensteinen
),
Padding(
padding: const EdgeInsets.symmetric(vertical: 4.0),
child: Column(
children: [
Text(
milestoneEmoji,
style: const TextStyle(fontSize: 20), // Emoji für Meilenstein
),
const SizedBox(height: 5),
Text(
milestoneText,
textAlign: TextAlign.center,
),
],
),
),
Padding(
padding: const EdgeInsets.symmetric(vertical: 4.0),
child: Icon(
milestoneReached ? CupertinoIcons.check_mark_circled_solid : CupertinoIcons.circle_fill,
size: 20,
color: milestoneReached ? CupertinoColors.systemGreen : CupertinoColors.black, // Icon, das den Status des Meilensteins anzeigt
),
),
],
);
}),
),
),
);
}

View File

@ -1,44 +1,79 @@
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter_application_1/enums.dart';
import 'package:flutter_application_1/translations.dart';
import 'package:flutter_application_1/widgets/expandable_widget.dart';
import 'package:flutter_application_1/widgets/second_page_widget.dart';
import 'package:flutter_application_1/widgets/custom_image_button_widget.dart';
import 'package:flutter_application_1/widgets/chart_widget.dart';
import 'package:flutter_application_1/widgets/milestone_timeline_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) {
// Liste von Meilensteinen mit Werten, Bildern und Texten.
// Erstellt ein Widget, das die Berechnungsergebnisse anzeigt
Widget buildResultWidget(BuildContext context, String compoundInterest, String investedMoney, String time, String monthlySavingsRate, String interestRate, PayoutInterval payoutInterval, List<double> investedMoneyList, List<double> compoundInterestList) {
// Liste von Meilensteinen mit Werten, Emojis und Beschreibungen
List<Map<String, dynamic>> milestoneList = [
{'value': 1329.0, 'emoji': '📱', 'text': 'iPhone 15 Pro Max\nPreis: 1329€'},
{'value': 3071.0, 'emoji': '🚲', 'text': 'Flyer Gotour6 3.40\nPreis: 3071€'},
{'value': 248157.0, 'emoji': '🏎️', 'text': 'Porsche 992 GT3 RS\nPreis: 248157€'},
{'value': 450000.0, 'emoji': '🏡', 'text': '150qm Einfamilienhaus\nPreis: ca. 450000€'},
{'value': 700.0, 'emoji': '📱', 'text': 'Smartphone\nPreis: 700€'},
{'value': 3250.0, 'emoji': '🚲', 'text': 'eBike\nPreis: 3250€'},
{'value': 20000.0, 'emoji': '🌎', 'text': 'Weltreise\nPreis: 20000€'},
{'value': 100000.0, 'emoji': '🏎️', 'text': 'Sportwagen\nPreis: 100000€'},
{'value': 350000.0, 'emoji': '🏡', 'text': '150qm Einfamilienhaus\nPreis: 350000€'},
];
return Column(
children: <Widget>[
CustomImageButton(
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => SecondPage(
title: 'Grafik',
widgetToShow: StackedColumnChart(
lowerValues: investedMoneyList,
upperValues: compoundInterestList,
)
),
),
);
},
backgroundImage: 'assets/images/button_bg1.jpg',
child: const Text(
'Grafik',
style: TextStyle(color: CupertinoColors.white, fontSize: 20),
),
),
const SizedBox(height: 20),
CustomImageButton(
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => SecondPage(
title: 'Meilensteine',
widgetToShow: buildMilestoneTimeline(milestoneList, double.parse(compoundInterest) - double.parse(investedMoney))
),
),
);
},
backgroundImage: 'assets/images/button_bg2.jpg',
child: const Text(
'Meilensteine',
style: TextStyle(color: CupertinoColors.white, fontSize: 20),
),
),
const SizedBox(height: 20),
_buildResultRow('Endkapital:', '$compoundInterest'),
_buildResultRow('Einzahlungen:', '$investedMoney'),
_buildResultRow('Erhaltene Zinsen:', '${double.parse(compoundInterest) - double.parse(investedMoney)}'),
const SizedBox(height: 20),
const SizedBox(height: 10),
Text(
'Wenn du über einen Zeitraum von $time Jahren ${translateInterval(payoutInterval)} $monthlySavingsRate€ mit einem Zinssatz von $interestRate% investierst, erreichst du am Ende ein Endkapital von $compoundInterest€. Dieses setzt sich aus Einzahlungen von $investedMoney€ und Zinsen bzw. Kapitalerträgen in Höhe von ${double.parse(compoundInterest) - double.parse(investedMoney)}€ zusammen.'
),
const SizedBox(height: 20),
ExpandableBox(
headerText: 'Grafik',
expandedContent: StackedColumnChart(
lowerValues: investedMoneyList,
upperValues: compoundInterestList,
),
),
const SizedBox(height: 5),
ExpandableBox(
headerText: 'Meilensteine',
expandedContent: buildMilestoneTimeline(milestoneList, double.parse(compoundInterest) - double.parse(investedMoney)),
),
],
);
}
// Erstellt eine Zeile mit einem Label und einem Wert
Widget _buildResultRow(String label, String value) {
return Padding(
padding: const EdgeInsets.symmetric(horizontal: 20),
@ -68,62 +103,3 @@ Widget _buildResultRow(String label, String value) {
),
);
}
// Erstellt die Meilenstein-Timeline.
Widget buildMilestoneTimeline(List<Map<String, dynamic>> milestones, double totalInterest) {
return SizedBox(
child: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: List.generate(milestones.length, (index) {
// Werte aus dem Meilenstein-Objekt extrahieren
double milestoneValue = milestones[index]['value'];
String milestoneEmoji = milestones[index]['emoji'];
String milestoneText = milestones[index]['text'];
bool milestoneReached = totalInterest >= milestoneValue;
return Column(
children: [
if (index > 0) // Zeigt eine vertikale Linie an zwischen den Meilensteinen
Container(
height: 50,
width: 2,
color: milestoneReached ? CupertinoColors.systemGreen : CupertinoColors.black,
),
Padding(
padding: const EdgeInsets.symmetric(vertical: 4.0),
child: Column(
children: [
Text(
milestoneEmoji,
style: const TextStyle(fontSize: 25),
),
const SizedBox(height: 5),
Text(
milestoneText,
textAlign: TextAlign.center,
style: const TextStyle(
fontWeight: FontWeight.bold,
),
),
],
),
),
// Zeigt ein Häkchen oder einen Kreis je nach Erreichen des Meilensteins an
Padding(
padding: const EdgeInsets.symmetric(vertical: 4.0),
child: Icon(
milestoneReached ? CupertinoIcons.check_mark_circled_solid : CupertinoIcons.circle_fill,
size: 20,
color: milestoneReached ? CupertinoColors.systemGreen : CupertinoColors.black,
),
),
],
);
}),
),
),
);
}

View File

@ -0,0 +1,50 @@
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
class SecondPage extends StatelessWidget {
final String title;
final Widget widgetToShow;
const SecondPage({
super.key,
required this.title,
required this.widgetToShow
});
@override
Widget build(BuildContext context) {
return Scaffold(
body: CustomScrollView(
slivers: <Widget>[
SliverToBoxAdapter(
child: Container(
padding: EdgeInsets.only(left: 10, right: 10, top: MediaQuery.of(context).padding.top + 10),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
IconButton(
icon: const Icon(CupertinoIcons.chevron_left, size: 15), // Zurück-Pfeil
onPressed: () {
Navigator.pop(context);
},
),
Text(
title,
style: const TextStyle(fontWeight: FontWeight.bold),
),
const SizedBox(width: 40), // Platzhalter für zentrierte Ausrichtung
],
),
),
),
SliverToBoxAdapter(
child: Padding(
padding: const EdgeInsets.all(10.0),
child: widgetToShow, // Anzeigen des mitgegebenen Widgets
),
),
],
),
);
}
}

View File

@ -60,8 +60,9 @@ flutter:
uses-material-design: true
# To add assets to your application, add an assets section, like this:
# assets:
# - assets/images/
assets:
- assets/images/button_bg1.jpg
- assets/images/button_bg2.jpg
# An image asset can refer to one or more resolution-specific "variants", see
# https://flutter.dev/assets-and-images/#resolution-aware