279 lines
10 KiB
Dart
279 lines
10 KiB
Dart
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/utils.dart';
|
|
import 'package:flutter_application_1/widgets/input_widget.dart';
|
|
import 'package:flutter_application_1/widgets/interval_widget.dart';
|
|
import 'package:flutter_application_1/widgets/result_widget.dart';
|
|
import 'package:flutter_application_1/widgets/error_widget.dart';
|
|
|
|
void main() {
|
|
runApp(const MyApp());
|
|
}
|
|
|
|
class MyApp extends StatelessWidget {
|
|
const MyApp({super.key});
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return MaterialApp(
|
|
title: 'Zinseszinsrechner',
|
|
theme: ThemeData(
|
|
colorScheme: ColorScheme.fromSeed(seedColor: CupertinoColors.white, background: CupertinoColors.white),
|
|
useMaterial3: true,
|
|
),
|
|
home: const MyHomePage(title: 'Zinseszinsrechner',),
|
|
debugShowCheckedModeBanner: false,
|
|
);
|
|
}
|
|
}
|
|
|
|
class MyHomePage extends StatefulWidget {
|
|
const MyHomePage({super.key, required this.title});
|
|
final String title;
|
|
|
|
@override
|
|
State<MyHomePage> createState() => _MyHomePageState();
|
|
}
|
|
|
|
class _MyHomePageState extends State<MyHomePage> {
|
|
// Controller und Fokus-Knoten für die Eingabefelder
|
|
final TextEditingController _initialCapitalController = TextEditingController();
|
|
final TextEditingController _monthlySavingsRateController = TextEditingController();
|
|
final TextEditingController _interestRateController = TextEditingController();
|
|
final TextEditingController _timeController = TextEditingController();
|
|
final FocusNode _initialCapitalFocusNode = FocusNode();
|
|
final FocusNode _monthlySavingsRateFocusNode = FocusNode();
|
|
final FocusNode _interestRateFocusNode = 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
|
|
void initState() {
|
|
super.initState();
|
|
|
|
// Listener für die Eingabefelder, um die Validierung durchzuführen und Standardwerte wiederherzustellen
|
|
_initialCapitalController.addListener(() {
|
|
setState(() {
|
|
_isInitialCapitalEntered = _initialCapitalController.text.isNotEmpty &&
|
|
isNumeric(_initialCapitalController.text);
|
|
restoreDefaultValuesIfEmpty(_initialCapitalController);
|
|
});
|
|
});
|
|
|
|
_monthlySavingsRateController.addListener(() {
|
|
setState(() {
|
|
_isMonthlySavingsRateEntered = _monthlySavingsRateController.text.isNotEmpty &&
|
|
isNumeric(_monthlySavingsRateController.text);
|
|
restoreDefaultValuesIfEmpty(_monthlySavingsRateController);
|
|
});
|
|
});
|
|
|
|
_interestRateController.addListener(() {
|
|
setState(() {
|
|
_isInterestRateEntered = _interestRateController.text.isNotEmpty &&
|
|
isNumeric(_interestRateController.text);
|
|
restoreDefaultValuesIfEmpty(_interestRateController);
|
|
});
|
|
});
|
|
|
|
_timeController.addListener(() {
|
|
setState(() {
|
|
_isTimeEntered = _timeController.text.isNotEmpty &&
|
|
isNumeric(_timeController.text);
|
|
restoreDefaultValuesIfEmpty(_timeController);
|
|
});
|
|
});
|
|
|
|
// Listener für die Fokus-Knoten, um die Eingabe zu runden, wenn der Fokus verloren geht
|
|
_initialCapitalFocusNode.addListener(() {
|
|
if (!_initialCapitalFocusNode.hasFocus) {
|
|
roundToInteger(_initialCapitalController);
|
|
}
|
|
});
|
|
|
|
_monthlySavingsRateFocusNode.addListener(() {
|
|
if (!_monthlySavingsRateFocusNode.hasFocus) {
|
|
roundToInteger(_monthlySavingsRateController);
|
|
}
|
|
});
|
|
|
|
_interestRateFocusNode.addListener(() {
|
|
if (!_interestRateFocusNode.hasFocus) {
|
|
roundToInteger(_interestRateController);
|
|
}
|
|
});
|
|
|
|
_timeFocusNode.addListener(() {
|
|
if (!_timeFocusNode.hasFocus) {
|
|
roundToInteger(_timeController);
|
|
}
|
|
});
|
|
|
|
// Setzen von Beispielwerten für die Eingabefelder
|
|
_initialCapitalController.text = '1000';
|
|
_monthlySavingsRateController.text = '50';
|
|
_interestRateController.text = '5';
|
|
_timeController.text = '10';
|
|
}
|
|
|
|
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() {
|
|
setState(() {
|
|
_initialCapital = double.parse(_initialCapitalController.text);
|
|
});
|
|
}
|
|
|
|
void setMonthlySavingsRate() {
|
|
setState(() {
|
|
_monthlySavingsRate = double.parse(_monthlySavingsRateController.text);
|
|
});
|
|
}
|
|
|
|
void setInterestRate() {
|
|
setState(() {
|
|
_interestRate = double.parse(_interestRateController.text);
|
|
});
|
|
}
|
|
|
|
void setTime() {
|
|
setState(() {
|
|
_time = double.parse(_timeController.text);
|
|
});
|
|
}
|
|
|
|
CalculationPerformed _isCalculated = CalculationPerformed.noFirstTimeItLoaded;
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return Scaffold(
|
|
body: SafeArea(
|
|
child: SingleChildScrollView(
|
|
physics: const BouncingScrollPhysics(),
|
|
child: Padding(
|
|
padding: const EdgeInsets.all(20.0),
|
|
child: Column(
|
|
crossAxisAlignment: CrossAxisAlignment.stretch,
|
|
children: <Widget>[
|
|
InputWidget(
|
|
label: 'Anfangskapital',
|
|
controller: _initialCapitalController,
|
|
focusNode: _initialCapitalFocusNode,
|
|
isValid: _isInitialCapitalEntered,
|
|
suffixText: '€',
|
|
tooltipText: 'Das Anfangskapital ist der Betrag, den Sie zu Beginn Ihrer Anlage haben.'
|
|
),
|
|
InputWidget(
|
|
label: 'Monatliche Sparrate',
|
|
controller: _monthlySavingsRateController,
|
|
focusNode: _monthlySavingsRateFocusNode,
|
|
isValid: _isMonthlySavingsRateEntered,
|
|
suffixText: '€',
|
|
tooltipText: 'Die monatliche Sparrate ist der Betrag, den Sie jeden Monat zu Ihrer Investition hinzufügen.'
|
|
),
|
|
InputWidget(
|
|
label: 'Jährlicher Zinssatz',
|
|
controller: _interestRateController,
|
|
focusNode: _interestRateFocusNode,
|
|
isValid: _isInterestRateEntered,
|
|
suffixText: '%',
|
|
tooltipText: 'Der jährliche Zinssatz ist der Prozentsatz, zu dem Ihr investiertes Kapital jedes Jahr wächst.'
|
|
),
|
|
InputWidget(
|
|
label: 'Anlagezeitraum',
|
|
controller: _timeController,
|
|
focusNode: _timeFocusNode,
|
|
isValid: _isTimeEntered,
|
|
suffixText: 'Jahre',
|
|
tooltipText: 'Der Anlagezeitraum ist die Zeitspanne, für die Sie planen, Ihr Geld anzulegen.'
|
|
),
|
|
IntervalWidget(
|
|
selectedInterval: translateInterval(_payoutInterval),
|
|
onChanged: (newInterval) {
|
|
setState(() {
|
|
_payoutInterval = newInterval == 'jährlich' ? PayoutInterval.yearly : PayoutInterval.monthly;
|
|
});
|
|
},
|
|
),
|
|
ElevatedButton(
|
|
onPressed: () {
|
|
if (_isInitialCapitalEntered &&
|
|
_isMonthlySavingsRateEntered &&
|
|
_isInterestRateEntered &&
|
|
_isTimeEntered) {
|
|
setInitialCapital();
|
|
setMonthlySavingsRate();
|
|
setInterestRate();
|
|
setTime();
|
|
_investedMoney = calculateInvestedMoney(_initialCapital, _monthlySavingsRate, _time, _investedMoneyList);
|
|
_compoundInterest = calculateCompoundInterest(
|
|
_initialCapital,
|
|
_monthlySavingsRate,
|
|
_interestRate,
|
|
_time,
|
|
_payoutInterval,
|
|
_investedMoneyList,
|
|
_compoundInterestList
|
|
);
|
|
_isCalculated = CalculationPerformed.yes;
|
|
} else {
|
|
_isCalculated = CalculationPerformed.no;
|
|
}
|
|
setState(() {});
|
|
},
|
|
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',
|
|
style: TextStyle(
|
|
fontWeight: FontWeight.bold,
|
|
),
|
|
),
|
|
),
|
|
const SizedBox(height: 20),
|
|
if(_isCalculated == CalculationPerformed.yes)
|
|
ResultWidget(
|
|
compoundInterest: '$_compoundInterest',
|
|
investedMoney: '$_investedMoney',
|
|
time: '$_time',
|
|
monthlySavingsRate: '$_monthlySavingsRate',
|
|
interestRate: '$_interestRate',
|
|
payoutInterval: _payoutInterval,
|
|
investedMoneyList: _investedMoneyList,
|
|
compoundInterestList: _compoundInterestList,
|
|
),
|
|
if(_isCalculated == CalculationPerformed.no)
|
|
const ErrWidget(
|
|
errorMessage: 'Ungültige Eingabe',
|
|
),
|
|
],
|
|
),
|
|
)
|
|
)
|
|
)
|
|
);
|
|
}
|
|
} |