flutter_application_1/lib/main.dart

324 lines
12 KiB
Dart

import 'package:flutter/material.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter_localizations/flutter_localizations.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.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';
import 'package:flutter_application_1/widgets/language_switcher_widget.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatefulWidget {
const MyApp({super.key});
@override
MyAppState createState() => MyAppState();
}
class MyAppState extends State<MyApp> {
Locale _locale = const Locale('de'); // Standard-Locale
void _changeLanguage(Locale locale) {
setState(() {
_locale = locale;
});
}
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Compound interest calculator',
localizationsDelegates: const [
AppLocalizations.delegate,
GlobalMaterialLocalizations.delegate,
GlobalWidgetsLocalizations.delegate,
GlobalCupertinoLocalizations.delegate,
],
supportedLocales: const [
Locale('en'), // English
Locale('de'), // Deutsch
],
locale: _locale,
theme: ThemeData(
colorScheme: ColorScheme.fromSeed(seedColor: CupertinoColors.white, background: CupertinoColors.white),
useMaterial3: true,
),
home: MyHomePage(
title: 'Compound interest calculator',
onLocaleChanged: _changeLanguage, // Übergibt die Sprachwechsel-Funktion an die Startseite
),
debugShowCheckedModeBanner: false,
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({super.key, required this.title, required this.onLocaleChanged});
final String title;
final Function(Locale) onLocaleChanged;
@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) {
final localizations = AppLocalizations.of(context)!;
return Scaffold(
body: SafeArea(
child: Stack(
children: [
SingleChildScrollView(
physics: const BouncingScrollPhysics(),
child: Padding(
padding: const EdgeInsets.all(20.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
InputWidget(
label: localizations.initial_capital,
controller: _initialCapitalController,
focusNode: _initialCapitalFocusNode,
isValid: _isInitialCapitalEntered,
suffixText: localizations.currency,
tooltipText: localizations.initial_capital_tooltiptext
),
InputWidget(
label: localizations.monthly_savings_rate,
controller: _monthlySavingsRateController,
focusNode: _monthlySavingsRateFocusNode,
isValid: _isMonthlySavingsRateEntered,
suffixText: localizations.currency,
tooltipText: localizations.monthly_savings_rate_tooltiptext
),
InputWidget(
label: localizations.interest_rate,
controller: _interestRateController,
focusNode: _interestRateFocusNode,
isValid: _isInterestRateEntered,
suffixText: '%',
tooltipText: localizations.interest_rate_tooltiptext
),
InputWidget(
label: localizations.investment_period,
controller: _timeController,
focusNode: _timeFocusNode,
isValid: _isTimeEntered,
suffixText: localizations.years,
tooltipText: localizations.investment_period_tooltiptext
),
IntervalWidget(
selectedInterval: _payoutInterval == PayoutInterval.yearly ? localizations.yearly : localizations.monthly,
onChanged: (newInterval) {
setState(() {
_payoutInterval = newInterval == localizations.yearly ? 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: Text(
localizations.calculate,
style: const TextStyle(
fontWeight: FontWeight.bold,
),
),
),
const SizedBox(height: 20),
if(_isCalculated == CalculationPerformed.yes)
ResultWidget(
compoundInterest: _compoundInterest.toStringAsFixed(0),
investedMoney: _investedMoney.toStringAsFixed(0),
time: _time.toStringAsFixed(0),
monthlySavingsRate: _monthlySavingsRate.toStringAsFixed(0),
interestRate: _interestRate.toStringAsFixed(0),
payoutInterval: _payoutInterval,
investedMoneyList: _investedMoneyList,
compoundInterestList: _compoundInterestList,
),
if(_isCalculated == CalculationPerformed.no)
ErrWidget(
errorMessage: localizations.invalid_input,
),
],
),
),
),
Positioned(
top: MediaQuery.of(context).size.height / 2 - 20,
right: 10,
child: LanguageSwitcher(
currentLocale: Localizations.localeOf(context),
onLocaleChanged: widget.onLocaleChanged,
),
),
],
),
),
);
}
}