diff --git a/assets/images/button_bg1.jpg b/assets/images/button_bg1.jpg new file mode 100644 index 0000000..24b7e5f Binary files /dev/null and b/assets/images/button_bg1.jpg differ diff --git a/assets/images/button_bg2.jpg b/assets/images/button_bg2.jpg new file mode 100644 index 0000000..c7d1ce8 Binary files /dev/null and b/assets/images/button_bg2.jpg differ diff --git a/lib/calculator.dart b/lib/calculator.dart new file mode 100644 index 0000000..af5b0da --- /dev/null +++ b/lib/calculator.dart @@ -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 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 investedMoneyList, List 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 +} diff --git a/lib/main.dart b/lib/main.dart index a54fa56..a46d912 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -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 { _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 _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 _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 _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 _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 { }); } - // 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 { 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(CupertinoColors.black), foregroundColor: MaterialStateProperty.all(CupertinoColors.white), + shape: MaterialStateProperty.all( + RoundedRectangleBorder( + borderRadius: BorderRadius.circular(5), + ), + ), ), child: const Text( 'Berechnen', @@ -242,8 +210,8 @@ class _MyHomePageState extends State { ), ), 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), ], ), ) diff --git a/lib/widgets/chart_widget.dart b/lib/widgets/chart_widget.dart index a8d4bc5..e5c4a96 100644 --- a/lib/widgets/chart_widget.dart +++ b/lib/widgets/chart_widget.dart @@ -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 lowerValues; - final List upperValues; + final List lowerValues; // Liste der unteren Werte für das Diagramm + final List 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: [ - // Untere Teil der Säule + // Serie für die Einzahlungen (untere Werte) StackedColumnSeries( 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( 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 _getLowerChartData() { List 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 _getUpperChartData() { List 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; diff --git a/lib/widgets/custom_image_button_widget.dart b/lib/widgets/custom_image_button_widget.dart new file mode 100644 index 0000000..852491c --- /dev/null +++ b/lib/widgets/custom_image_button_widget.dart @@ -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, + ), + ), + ), + ); + } +} diff --git a/lib/widgets/expandable_widget.dart b/lib/widgets/expandable_widget.dart deleted file mode 100644 index 7051028..0000000 --- a/lib/widgets/expandable_widget.dart +++ /dev/null @@ -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 { - 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, - ), - ) - ], - ); - } -} diff --git a/lib/widgets/input_widget.dart b/lib/widgets/input_widget.dart index 96a84a3..98f4d07 100644 --- a/lib/widgets/input_widget.dart +++ b/lib/widgets/input_widget.dart @@ -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, diff --git a/lib/widgets/interval_widget.dart b/lib/widgets/interval_widget.dart index 73b8746..2356b53 100644 --- a/lib/widgets/interval_widget.dart +++ b/lib/widgets/interval_widget.dart @@ -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 { - bool isExpanded = false; +class IntervalWidgetState extends State { + 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 { ), ), 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 { ), ] ), - // 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 { 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 { 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 { }, ).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), diff --git a/lib/widgets/milestone_timeline_widget.dart b/lib/widgets/milestone_timeline_widget.dart new file mode 100644 index 0000000..3eb3233 --- /dev/null +++ b/lib/widgets/milestone_timeline_widget.dart @@ -0,0 +1,52 @@ +// Erstellt eine Zeitleiste für Meilensteine +import 'package:flutter/cupertino.dart'; + +Widget buildMilestoneTimeline(List> 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 + ), + ), + ], + ); + }), + ), + ), + ); +} diff --git a/lib/widgets/result_widget.dart b/lib/widgets/result_widget.dart index afddb2d..e04a2d3 100644 --- a/lib/widgets/result_widget.dart +++ b/lib/widgets/result_widget.dart @@ -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 investedMoneyList, List 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 investedMoneyList, List compoundInterestList) { + // Liste von Meilensteinen mit Werten, Emojis und Beschreibungen List> 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: [ + 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> 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, - ), - ), - ], - ); - }), - ), - ), - ); -} - diff --git a/lib/widgets/second_page_widget.dart b/lib/widgets/second_page_widget.dart new file mode 100644 index 0000000..95e3e2d --- /dev/null +++ b/lib/widgets/second_page_widget.dart @@ -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: [ + 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 + ), + ), + ], + ), + ); + } +} diff --git a/pubspec.yaml b/pubspec.yaml index b77cfc7..5f5a39c 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -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