Darkmode+ budgetchecker finished
parent
5582e7b4fa
commit
db9abf9866
|
@ -4,6 +4,7 @@ import 'package:easy_localization/easy_localization.dart';
|
|||
import 'package:flutter_neumorphic/flutter_neumorphic.dart';
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
import 'package:tests/saving_tips.dart';
|
||||
import 'package:tests/theme/theme_constants.dart';
|
||||
import 'package:tests/transaction/transaction_dialog.dart';
|
||||
import 'package:tests/transaction/transaction.dart';
|
||||
import '../main.dart';
|
||||
|
@ -30,35 +31,41 @@ class AccountDetailPageState extends State<AccountDetailPage>
|
|||
List<Transaction> incomeTransactions = [];
|
||||
List<Transaction> expenseTransactions = [];
|
||||
List<ExpenseData> expenseData = [];
|
||||
String _selectedCurrency="€";
|
||||
String _selectedCurrency = "€";
|
||||
|
||||
Future<String> getCurrencyFromSharedPreferences(String key) async {
|
||||
SharedPreferences prefs = await SharedPreferences.getInstance();
|
||||
if (prefs.getString(key)=="Euro"){
|
||||
_selectedCurrency="€";
|
||||
if (prefs.getString(key) == "Euro") {
|
||||
_selectedCurrency = "€";
|
||||
}
|
||||
if (prefs.getString(key)=="Dollar"){
|
||||
_selectedCurrency=r"$";
|
||||
if (prefs.getString(key) == "Dollar") {
|
||||
_selectedCurrency = r"$";
|
||||
}
|
||||
if (prefs.getString(key)=="CHF"){
|
||||
_selectedCurrency="CHF";
|
||||
if (prefs.getString(key) == "CHF") {
|
||||
_selectedCurrency = "CHF";
|
||||
}
|
||||
|
||||
return prefs.getString(key) ?? 'Euro';
|
||||
}
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_tabController = TabController(length: 3, vsync: this);
|
||||
|
||||
getCurrencyFromSharedPreferences("currency").then((value) {
|
||||
setState(() {
|
||||
|
||||
});
|
||||
setState(() {});
|
||||
});
|
||||
loadMaxProgress();
|
||||
loadTransactions();
|
||||
}
|
||||
|
||||
void loadMaxProgress() async {
|
||||
double storedMaxProgress = await getMaxProgress();
|
||||
setState(() {
|
||||
maxProgress = storedMaxProgress;
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_tabController.dispose();
|
||||
|
@ -141,8 +148,24 @@ class AccountDetailPageState extends State<AccountDetailPage>
|
|||
final _budgetController = TextEditingController();
|
||||
double progress = 0;
|
||||
|
||||
double submitbudget() {
|
||||
return progress = double.parse(_budgetController.text.trim());
|
||||
double submitBudget() {
|
||||
if (_budgetController.text.isNotEmpty) {
|
||||
double budgetValue = double.parse(_budgetController.text);
|
||||
SharedPreferences.getInstance().then((prefs) {
|
||||
prefs.setDouble("maxProgress", budgetValue);
|
||||
});
|
||||
setState(() {
|
||||
maxProgress = budgetValue;
|
||||
});
|
||||
return budgetValue;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
Future<double> getMaxProgress() async {
|
||||
SharedPreferences prefs = await SharedPreferences.getInstance();
|
||||
double maxProgress = prefs.getDouble('maxProgress') ?? 1000;
|
||||
return maxProgress;
|
||||
}
|
||||
|
||||
@override
|
||||
|
@ -155,9 +178,9 @@ class AccountDetailPageState extends State<AccountDetailPage>
|
|||
Padding(
|
||||
padding: const EdgeInsets.only(right: 10.0),
|
||||
child: IconButton(
|
||||
icon: const Icon(
|
||||
icon: Icon(
|
||||
Icons.info,
|
||||
color: Colors.grey,
|
||||
color: Theme.of(context).unselectedWidgetColor,
|
||||
),
|
||||
onPressed: () {
|
||||
showDialog(
|
||||
|
@ -171,11 +194,12 @@ class AccountDetailPageState extends State<AccountDetailPage>
|
|||
toolbarHeight: 80,
|
||||
title: Text(
|
||||
widget.account.name,
|
||||
style: const TextStyle(
|
||||
fontSize: 18,
|
||||
fontWeight: FontWeight.bold,
|
||||
color: Colors.black54,
|
||||
),
|
||||
style: TextStyle(
|
||||
fontSize: 18,
|
||||
fontWeight: FontWeight.bold,
|
||||
color: Theme.of(context).brightness == Brightness.dark
|
||||
? Colors.white70
|
||||
: Colors.black87),
|
||||
),
|
||||
centerTitle: true,
|
||||
shape: const RoundedRectangleBorder(
|
||||
|
@ -184,13 +208,12 @@ class AccountDetailPageState extends State<AccountDetailPage>
|
|||
bottomRight: Radius.circular(15),
|
||||
),
|
||||
),
|
||||
shadowColor: Colors.grey.shade300,
|
||||
leading: Padding(
|
||||
padding: const EdgeInsets.only(left: 16.0),
|
||||
child: NeumorphicButton(
|
||||
onPressed: () {
|
||||
Navigator.pop(context); // Zurück zur vorherigen Seite
|
||||
Navigator.pushReplacement( // Neue Seite öffnen und vorherige Seite ersetzen
|
||||
Navigator.pop(context);
|
||||
Navigator.pushReplacement(
|
||||
context,
|
||||
MaterialPageRoute(builder: (context) => const HomePage()),
|
||||
);
|
||||
|
@ -199,11 +222,20 @@ class AccountDetailPageState extends State<AccountDetailPage>
|
|||
shape: NeumorphicShape.flat,
|
||||
boxShape: const NeumorphicBoxShape.circle(),
|
||||
depth: 6,
|
||||
shadowLightColor: Theme.of(context).brightness == Brightness.light
|
||||
? const NeumorphicStyle().shadowLightColor
|
||||
: Theme.of(context).shadowColor,
|
||||
shadowDarkColor: Theme.of(context).brightness == Brightness.dark
|
||||
? const NeumorphicStyle().shadowDarkColor
|
||||
: grey400,
|
||||
color: Theme.of(context).brightness == Brightness.light
|
||||
? grey200
|
||||
: grey800,
|
||||
intensity: 0.9,
|
||||
color: Colors.grey.shade100,
|
||||
),
|
||||
padding: const EdgeInsets.all(10),
|
||||
child: const Icon(Icons.arrow_back, color: Colors.black38),
|
||||
padding: const EdgeInsets.all(8),
|
||||
child: Icon(Icons.arrow_back,
|
||||
color: Theme.of(context).unselectedWidgetColor),
|
||||
),
|
||||
),
|
||||
),
|
||||
|
@ -211,12 +243,12 @@ class AccountDetailPageState extends State<AccountDetailPage>
|
|||
children: [
|
||||
TabBar(
|
||||
controller: _tabController,
|
||||
labelColor: Colors.black,
|
||||
labelColor: Theme.of(context).cardColor,
|
||||
labelStyle: const TextStyle(fontSize: 14),
|
||||
unselectedLabelColor: Colors.black54,
|
||||
unselectedLabelColor: Theme.of(context).unselectedWidgetColor,
|
||||
indicator: MaterialIndicator(
|
||||
height: 4,
|
||||
color: Colors.black54,
|
||||
color: Theme.of(context).unselectedWidgetColor,
|
||||
topLeftRadius: 8,
|
||||
topRightRadius: 8,
|
||||
horizontalPadding: 45,
|
||||
|
@ -249,16 +281,27 @@ class AccountDetailPageState extends State<AccountDetailPage>
|
|||
Neumorphic(
|
||||
margin: const EdgeInsets.all(14),
|
||||
style: NeumorphicStyle(
|
||||
color: Colors.grey.shade100,
|
||||
shadowLightColor:
|
||||
Theme.of(context).brightness == Brightness.light
|
||||
? const NeumorphicStyle().shadowLightColor
|
||||
: Theme.of(context).shadowColor,
|
||||
shadowDarkColor:
|
||||
Theme.of(context).brightness == Brightness.dark
|
||||
? const NeumorphicStyle().shadowDarkColor
|
||||
: grey400,
|
||||
color: Theme.of(context).brightness == Brightness.light
|
||||
? grey200
|
||||
: grey800,
|
||||
boxShape: NeumorphicBoxShape.roundRect(
|
||||
BorderRadius.circular(15)),
|
||||
depth: -5,
|
||||
intensity: 0.8,
|
||||
),
|
||||
child: TextFormField(
|
||||
controller: _budgetController,
|
||||
keyboardType: TextInputType.number,
|
||||
decoration: InputDecoration(
|
||||
labelText: 'enteramount'.tr(),
|
||||
labelText: 'enterbudget'.tr(),
|
||||
contentPadding: const EdgeInsets.only(
|
||||
left: 16, bottom: 8, top: 8),
|
||||
border: InputBorder.none,
|
||||
|
@ -268,13 +311,25 @@ class AccountDetailPageState extends State<AccountDetailPage>
|
|||
const SizedBox(height: 16),
|
||||
NeumorphicButton(
|
||||
onPressed: () {
|
||||
progress = submitbudget();
|
||||
setState(() {
|
||||
submitBudget();
|
||||
});
|
||||
},
|
||||
style: NeumorphicStyle(
|
||||
boxShape: NeumorphicBoxShape.roundRect(
|
||||
BorderRadius.circular(12),
|
||||
),
|
||||
color: Colors.grey.shade100,
|
||||
shadowLightColor:
|
||||
Theme.of(context).brightness == Brightness.light
|
||||
? const NeumorphicStyle().shadowLightColor
|
||||
: Theme.of(context).shadowColor,
|
||||
shadowDarkColor:
|
||||
Theme.of(context).brightness == Brightness.dark
|
||||
? const NeumorphicStyle().shadowDarkColor
|
||||
: grey400,
|
||||
color: Theme.of(context).brightness == Brightness.light
|
||||
? grey200
|
||||
: grey800,
|
||||
depth: 8,
|
||||
intensity: 0.9,
|
||||
),
|
||||
|
@ -295,15 +350,23 @@ class AccountDetailPageState extends State<AccountDetailPage>
|
|||
style: NeumorphicStyle(
|
||||
depth: 8,
|
||||
intensity: 1,
|
||||
shadowDarkColor: Colors.grey.shade400,
|
||||
color: Colors.grey.shade100,
|
||||
shadowLightColor: Theme.of(context).brightness == Brightness.light
|
||||
? const NeumorphicStyle().shadowLightColor
|
||||
: Theme.of(context).shadowColor,
|
||||
shadowDarkColor: Theme.of(context).brightness == Brightness.dark
|
||||
? const NeumorphicStyle().shadowDarkColor
|
||||
: grey400,
|
||||
color: Theme.of(context).brightness == Brightness.light
|
||||
? grey200
|
||||
: grey800,
|
||||
boxShape: const NeumorphicBoxShape.circle(),
|
||||
),
|
||||
padding: const EdgeInsets.all(16),
|
||||
child: const Icon(
|
||||
child: Icon(
|
||||
Icons.add,
|
||||
size: 40,
|
||||
color: Colors.black12,
|
||||
size: 60,
|
||||
color: Theme.of(context).brightness == Brightness.light
|
||||
? Colors.black12
|
||||
: Colors.white12,
|
||||
),
|
||||
),
|
||||
);
|
||||
|
@ -311,14 +374,20 @@ class AccountDetailPageState extends State<AccountDetailPage>
|
|||
|
||||
final ValueNotifier<double> _valueNotifier = ValueNotifier(0);
|
||||
|
||||
double maxProgress = 500;
|
||||
|
||||
Widget monthlybudgetplanner() {
|
||||
return CircularSeekBar(
|
||||
width: double.infinity,
|
||||
height: 300,
|
||||
trackColor: Colors.black12,
|
||||
progress: 500,
|
||||
trackColor: Theme.of(context).brightness == Brightness.light
|
||||
? Colors.black12
|
||||
: Colors.white12,
|
||||
progress: calculateMonthlyExpensesTotal(),
|
||||
minProgress: 0,
|
||||
maxProgress: 800,
|
||||
maxProgress: calculateMonthlyExpensesTotal() > maxProgress
|
||||
? calculateMonthlyExpensesTotal()
|
||||
: maxProgress,
|
||||
barWidth: 17,
|
||||
startAngle: 45,
|
||||
sweepAngle: 270,
|
||||
|
@ -338,10 +407,9 @@ class AccountDetailPageState extends State<AccountDetailPage>
|
|||
],
|
||||
innerThumbRadius: 0,
|
||||
innerThumbStrokeWidth: 12,
|
||||
innerThumbColor: Colors.white,
|
||||
innerThumbColor: Theme.of(context).cardColor,
|
||||
outerThumbRadius: 0,
|
||||
outerThumbStrokeWidth: 15,
|
||||
outerThumbColor: Colors.blueAccent,
|
||||
dashWidth: 1.5,
|
||||
dashGap: 1.9,
|
||||
animation: true,
|
||||
|
@ -350,24 +418,59 @@ class AccountDetailPageState extends State<AccountDetailPage>
|
|||
valueNotifier: _valueNotifier,
|
||||
child: Center(
|
||||
child: ValueListenableBuilder(
|
||||
valueListenable: _valueNotifier,
|
||||
builder: (_, double value, __) => Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Text(
|
||||
'${value.round()}$_selectedCurrency',
|
||||
),
|
||||
Text(
|
||||
'progress'.tr(),
|
||||
),
|
||||
],
|
||||
)),
|
||||
valueListenable: _valueNotifier,
|
||||
builder: (_, double value, __) {
|
||||
final isMaxProgressReached = value >= maxProgress;
|
||||
final textStyle = TextStyle(
|
||||
fontSize: 15,
|
||||
fontWeight:
|
||||
isMaxProgressReached ? FontWeight.w600 : FontWeight.w300,
|
||||
);
|
||||
|
||||
return Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
if (isMaxProgressReached)
|
||||
Text(
|
||||
"budgetmax".tr(),
|
||||
style: TextStyle(
|
||||
fontSize: 20,
|
||||
fontWeight: FontWeight.bold,
|
||||
color: Theme.of(context).cardColor),
|
||||
)
|
||||
else
|
||||
Text(
|
||||
'${value.round()}$_selectedCurrency',
|
||||
style: TextStyle(
|
||||
fontSize: 24, color: Theme.of(context).cardColor),
|
||||
),
|
||||
const SizedBox(
|
||||
height: 10,
|
||||
),
|
||||
isMaxProgressReached
|
||||
? Text('hint'.tr(),
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(color: Theme.of(context).cardColor))
|
||||
: Text('progress'.tr(),
|
||||
style: TextStyle(color: Theme.of(context).cardColor)),
|
||||
const SizedBox(height: 10),
|
||||
isMaxProgressReached
|
||||
? Container()
|
||||
: Text(
|
||||
'Budget: $maxProgress',
|
||||
style: textStyle,
|
||||
),
|
||||
],
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildTransactionsList(List<Transaction> transactionsList) {
|
||||
return ListView.builder(
|
||||
physics: const BouncingScrollPhysics(),
|
||||
itemCount: transactionsList.length,
|
||||
itemBuilder: (context, index) {
|
||||
return ListTile(
|
||||
|
@ -389,11 +492,25 @@ class AccountDetailPageState extends State<AccountDetailPage>
|
|||
);
|
||||
}
|
||||
|
||||
double calculateMonthlyExpensesTotal() {
|
||||
double total = 0;
|
||||
for (var transaction in expenseTransactions) {
|
||||
String month = DateFormat('yyyy-MM').format(transaction.date);
|
||||
if (month == DateFormat('yyyy-MM').format(DateTime.now())) {
|
||||
total += transaction.amount;
|
||||
}
|
||||
}
|
||||
return total;
|
||||
}
|
||||
|
||||
Widget _buildExpenseChart() {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.all(8.0),
|
||||
child: Card(
|
||||
elevation: 4.0,
|
||||
color: Theme.of(context).brightness == Brightness.light
|
||||
? grey400
|
||||
: grey800,
|
||||
elevation: 6.0,
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(16.0),
|
||||
child: MonthlyExpensesChart(data: expenseData),
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:flutter_neumorphic/flutter_neumorphic.dart';
|
||||
import '../theme/theme_constants.dart';
|
||||
import 'account.dart';
|
||||
|
||||
class AddAccountDialog extends StatefulWidget {
|
||||
|
@ -33,7 +34,6 @@ class AddAccountDialogState extends State<AddAccountDialog> {
|
|||
balance: balance,
|
||||
);
|
||||
widget.addAccount(account);
|
||||
|
||||
Navigator.of(context).pop();
|
||||
}
|
||||
}
|
||||
|
@ -48,7 +48,6 @@ class AddAccountDialogState extends State<AddAccountDialog> {
|
|||
'addaccount'.tr(),
|
||||
),
|
||||
titleTextStyle: const TextStyle(
|
||||
color: Colors.black54,
|
||||
fontSize: 20,
|
||||
),
|
||||
content: Form(
|
||||
|
@ -60,7 +59,16 @@ class AddAccountDialogState extends State<AddAccountDialog> {
|
|||
style: NeumorphicStyle(
|
||||
depth: -5,
|
||||
intensity: 0.8,
|
||||
color: Colors.grey.shade100,
|
||||
shadowLightColor:
|
||||
Theme.of(context).brightness == Brightness.light
|
||||
? const NeumorphicStyle().shadowLightColor
|
||||
: Theme.of(context).shadowColor,
|
||||
shadowDarkColor: Theme.of(context).brightness == Brightness.dark
|
||||
? const NeumorphicStyle().shadowDarkColor
|
||||
: grey400,
|
||||
color: Theme.of(context).brightness == Brightness.light
|
||||
? grey200
|
||||
: grey800,
|
||||
boxShape: NeumorphicBoxShape.roundRect(
|
||||
BorderRadius.circular(12),
|
||||
),
|
||||
|
@ -85,7 +93,16 @@ class AddAccountDialogState extends State<AddAccountDialog> {
|
|||
style: NeumorphicStyle(
|
||||
depth: -5,
|
||||
intensity: 0.8,
|
||||
color: Colors.grey.shade100,
|
||||
shadowLightColor:
|
||||
Theme.of(context).brightness == Brightness.light
|
||||
? const NeumorphicStyle().shadowLightColor
|
||||
: Theme.of(context).shadowColor,
|
||||
shadowDarkColor: Theme.of(context).brightness == Brightness.dark
|
||||
? const NeumorphicStyle().shadowDarkColor
|
||||
: grey400,
|
||||
color: Theme.of(context).brightness == Brightness.light
|
||||
? grey200
|
||||
: grey800,
|
||||
boxShape: NeumorphicBoxShape.roundRect(
|
||||
BorderRadius.circular(12),
|
||||
),
|
||||
|
@ -114,6 +131,7 @@ class AddAccountDialogState extends State<AddAccountDialog> {
|
|||
),
|
||||
actions: [
|
||||
NeumorphicButton(
|
||||
margin: const EdgeInsets.fromLTRB(0, 0, 4, 4),
|
||||
onPressed: () {
|
||||
Navigator.of(context).pop();
|
||||
},
|
||||
|
@ -124,7 +142,15 @@ class AddAccountDialogState extends State<AddAccountDialog> {
|
|||
boxShape: NeumorphicBoxShape.roundRect(
|
||||
BorderRadius.circular(12),
|
||||
),
|
||||
color: Colors.grey.shade100,
|
||||
shadowLightColor: Theme.of(context).brightness == Brightness.light
|
||||
? const NeumorphicStyle().shadowLightColor
|
||||
: Theme.of(context).shadowColor,
|
||||
shadowDarkColor: Theme.of(context).brightness == Brightness.dark
|
||||
? const NeumorphicStyle().shadowDarkColor
|
||||
: grey400,
|
||||
color: Theme.of(context).brightness == Brightness.light
|
||||
? grey200
|
||||
: grey800,
|
||||
),
|
||||
padding: const EdgeInsets.symmetric(vertical: 12, horizontal: 16),
|
||||
child: Text(
|
||||
|
@ -144,7 +170,15 @@ class AddAccountDialogState extends State<AddAccountDialog> {
|
|||
boxShape: NeumorphicBoxShape.roundRect(
|
||||
BorderRadius.circular(12),
|
||||
),
|
||||
color: Colors.grey.shade100,
|
||||
shadowLightColor: Theme.of(context).brightness == Brightness.light
|
||||
? const NeumorphicStyle().shadowLightColor
|
||||
: Theme.of(context).shadowColor,
|
||||
shadowDarkColor: Theme.of(context).brightness == Brightness.dark
|
||||
? const NeumorphicStyle().shadowDarkColor
|
||||
: grey400,
|
||||
color: Theme.of(context).brightness == Brightness.light
|
||||
? grey200
|
||||
: grey800,
|
||||
),
|
||||
padding: const EdgeInsets.symmetric(vertical: 12, horizontal: 16),
|
||||
child: Text(
|
||||
|
|
|
@ -1,15 +1,15 @@
|
|||
{
|
||||
"title" : "My Finance Planner",
|
||||
"delete" : "Löschen",
|
||||
"deleteaccount" : "Account löschen",
|
||||
"sure" : "Sind Sie sicher, dass Sie dieses Konto löschen möchten?",
|
||||
"balance" : "Bilanz",
|
||||
"addaccount" : "Konto hinzufügen",
|
||||
"entername" : "Bitte geben Sie einen Namen ein",
|
||||
"enterbalance" : "Bitte geben Sie einen Saldo ein",
|
||||
"entervalidnumber" : "Bitte geben Sie eine gültige Nummer ein",
|
||||
"cancel" : "Abbrechen",
|
||||
"add" : "Hinzufügen",
|
||||
"title": "My Finance Planner",
|
||||
"delete": "Löschen",
|
||||
"deleteaccount": "Account löschen",
|
||||
"sure": "Sind Sie sicher, dass Sie dieses Konto löschen möchten?",
|
||||
"balance": "Bilanz",
|
||||
"addaccount": "Konto hinzufügen",
|
||||
"entername": "Bitte geben Sie einen Namen ein",
|
||||
"enterbalance": "Bitte geben Sie einen Saldo ein",
|
||||
"entervalidnumber": "Bitte geben Sie eine gültige Nummer ein",
|
||||
"cancel": "Abbrechen",
|
||||
"add": "Hinzufügen",
|
||||
"income": "Einnahmen",
|
||||
"expenditures": "Ausgaben",
|
||||
"addtrans": "Transaktion hinzufügen",
|
||||
|
@ -24,5 +24,23 @@
|
|||
"budget": "Budgetcheck",
|
||||
"progress": "von deinem Budget ausgegeben",
|
||||
"monthlyexpenses": "Monatliche Ausgaben",
|
||||
"close": "Schließen"
|
||||
"close": "Schließen",
|
||||
"tip1": "Spare jeden Monat einen festen Betrag.",
|
||||
"tip2": "Vergleiche Preise, bevor du etwas kaufst.",
|
||||
"tip3": "Vermeide unnötige Ausgaben.",
|
||||
"tip4": "Setze dir konkrete Sparziele.",
|
||||
"tip5": "Überprüfe regelmäßig deine Ausgaben.",
|
||||
"tip6": "Verkaufe Dinge, die du nicht mehr brauchst.",
|
||||
"tip7": "Nutze Cashback-Programme beim Einkaufen.",
|
||||
"tip8": "Koche selbst anstatt auswärts zu essen.",
|
||||
"tip9": "Nutze kostenlose Angebote und Gutscheine.",
|
||||
"tip10": "Vermeide Impulskäufe und schlafe vor größeren Ausgaben eine Nacht darüber.",
|
||||
"tip11": "Fahre mit dem Fahrrad oder öffentlichen Verkehrsmitteln anstatt mit dem Auto.",
|
||||
"tip12": "Plane deine Mahlzeiten im Voraus, um Lebensmittelverschwendung zu vermeiden.",
|
||||
"tip13": "Vergleiche Versicherungen und Verträge, um Geld zu sparen.",
|
||||
"tip14": "Mache deine eigenen Reinigungsmittel statt teure Produkte zu kaufen.",
|
||||
"tip15": "Nutze kostenlose Online-Ressourcen für Weiterbildung und Hobbys.",
|
||||
"hint": "Spartipps gefällig? \nDrücke auf den Info-Button",
|
||||
"budgetmax": "Budget verbraucht!",
|
||||
"enterbudget": "Budget eingeben"
|
||||
}
|
|
@ -1,15 +1,15 @@
|
|||
{
|
||||
"title" : "My Finance Planner",
|
||||
"delete" : "Delete",
|
||||
"deleteaccount" : "Delete account",
|
||||
"sure" : "Are you sure you want to delete this account?",
|
||||
"balance" : "Balance",
|
||||
"addaccount" : "Add account",
|
||||
"entername" : "Please enter a name",
|
||||
"enterbalance" : "Please enter a balance",
|
||||
"entervalidnumber" : "Please enter a valid number",
|
||||
"cancel" : "Cancel",
|
||||
"add" : "Add",
|
||||
"title": "My Finance Planner",
|
||||
"delete": "Delete",
|
||||
"deleteaccount": "Delete account",
|
||||
"sure": "Are you sure you want to delete this account?",
|
||||
"balance": "Balance",
|
||||
"addaccount": "Add account",
|
||||
"entername": "Please enter a name",
|
||||
"enterbalance": "Please enter a balance",
|
||||
"entervalidnumber": "Please enter a valid number",
|
||||
"cancel": "Cancel",
|
||||
"add": "Add",
|
||||
"income": "Income",
|
||||
"expenditures": "Expenses",
|
||||
"addtrans": "Add transaction",
|
||||
|
@ -24,5 +24,23 @@
|
|||
"budget": "Budget check",
|
||||
"progress": "of your budget spent",
|
||||
"monthlyexpenses": "Monthly Expenses",
|
||||
"close": "Close"
|
||||
"close": "Close",
|
||||
"tip1":"Save a fixed amount every month",
|
||||
"tip2":"Compare prices before you buy anything",
|
||||
"tip3":"Avoid unnecessary spending.",
|
||||
"tip4":"Set specific savings goals.",
|
||||
"tip5":"Review your spending regularly.",
|
||||
"tip6":"Sell things you no longer need",
|
||||
"tip7":"Take advantage of cash-back programs when shopping.",
|
||||
"tip8":"Cook for yourself instead of eating out.",
|
||||
"tip9":"Take advantage of free offers and coupons.",
|
||||
"tip10":"Avoid impulse buys and sleep on it before spending big.",
|
||||
"tip11":"Ride a bike or take public transportation instead of driving.",
|
||||
"tip12":"Plan your meals ahead of time to avoid food waste.",
|
||||
"tip13":"Compare insurance policies and contracts to save money.",
|
||||
"tip14":"Make your own cleaning supplies instead of buying expensive products.",
|
||||
"tip15":"Use free online resources for continuing education and hobbies.",
|
||||
"hint": "Need saving tips? \nPress the info button",
|
||||
"budgetmax": "Budget spent!",
|
||||
"enterbudget": "Enter budget"
|
||||
}
|
|
@ -1,5 +1,6 @@
|
|||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:syncfusion_flutter_charts/charts.dart';
|
||||
import 'package:tests/theme/theme_constants.dart';
|
||||
import 'expense_data.dart';
|
||||
import 'package:flutter_neumorphic/flutter_neumorphic.dart';
|
||||
|
||||
|
@ -16,13 +17,22 @@ class MonthlyExpensesChart extends StatelessWidget {
|
|||
style: NeumorphicStyle(
|
||||
shape: NeumorphicShape.flat,
|
||||
depth: 8,
|
||||
intensity: 0.6,
|
||||
intensity: 0.7,
|
||||
surfaceIntensity: 0.25,
|
||||
shadowLightColor: Colors.white,
|
||||
shadowDarkColor: Colors.black87,
|
||||
color: Colors.grey[100],
|
||||
shadowLightColor: Theme.of(context).brightness == Brightness.light
|
||||
? const NeumorphicStyle().shadowLightColor
|
||||
: grey600,
|
||||
shadowDarkColor: Theme.of(context).brightness == Brightness.dark
|
||||
? const NeumorphicStyle().shadowDarkColor
|
||||
: grey400,
|
||||
color: Theme.of(context).brightness == Brightness.light
|
||||
? grey200
|
||||
: grey800,
|
||||
),
|
||||
child: SfCartesianChart(
|
||||
backgroundColor: Theme.of(context).brightness == Brightness.light
|
||||
? grey200
|
||||
: grey700,
|
||||
primaryXAxis: CategoryAxis(),
|
||||
series: _buildChartSeries(),
|
||||
tooltipBehavior: TooltipBehavior(enable: true),
|
||||
|
@ -51,4 +61,4 @@ class MonthlyExpensesChart extends StatelessWidget {
|
|||
),
|
||||
];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
244
lib/main.dart
244
lib/main.dart
|
@ -2,6 +2,7 @@ import 'dart:convert';
|
|||
import 'package:awesome_dialog/awesome_dialog.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:flutter_neumorphic/flutter_neumorphic.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
import 'package:tests/preferences.dart';
|
||||
import 'package:tests/theme/theme_constants.dart';
|
||||
|
@ -15,14 +16,16 @@ Future<void> main() async {
|
|||
WidgetsFlutterBinding.ensureInitialized();
|
||||
await EasyLocalization.ensureInitialized();
|
||||
runApp(
|
||||
EasyLocalization(
|
||||
supportedLocales: const [Locale('en', 'US'), Locale('de', 'DE')],
|
||||
path: 'lib/assets/translations',
|
||||
// <-- change the path of the translation files
|
||||
fallbackLocale: const Locale('en', 'US'),
|
||||
child: const FinancialPlannerApp()),
|
||||
);
|
||||
}
|
||||
ChangeNotifierProvider(
|
||||
create: (context) => ThemeManager(),
|
||||
child: EasyLocalization(
|
||||
supportedLocales: const [Locale('en', 'US'), Locale('de', 'DE')],
|
||||
path: 'lib/assets/translations',
|
||||
// <-- change the path of the translation files
|
||||
fallbackLocale: const Locale('en', 'US'),
|
||||
child: const FinancialPlannerApp()),
|
||||
));
|
||||
}
|
||||
|
||||
ThemeManager _themeManager = ThemeManager();
|
||||
|
||||
|
@ -31,7 +34,8 @@ class FinancialPlannerApp extends StatelessWidget {
|
|||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
SystemChrome.setEnabledSystemUIMode(SystemUiMode.manual, overlays: []);
|
||||
SystemChrome.setEnabledSystemUIMode(
|
||||
SystemUiMode.manual, overlays: [SystemUiOverlay.top]);
|
||||
return MaterialApp(
|
||||
localizationsDelegates: context.localizationDelegates,
|
||||
supportedLocales: context.supportedLocales,
|
||||
|
@ -40,7 +44,7 @@ class FinancialPlannerApp extends StatelessWidget {
|
|||
title: 'title'.tr(),
|
||||
theme: lightTheme,
|
||||
darkTheme: darkTheme,
|
||||
themeMode: _themeManager.themeMode,
|
||||
themeMode: Provider.of<ThemeManager>(context).themeMode,
|
||||
home: const HomePage(),
|
||||
);
|
||||
}
|
||||
|
@ -55,18 +59,18 @@ class HomePage extends StatefulWidget {
|
|||
|
||||
class HomePageState extends State<HomePage> {
|
||||
List<Account> accounts = [];
|
||||
String _selectedCurrency="€";
|
||||
String _selectedCurrency = "€";
|
||||
|
||||
Future<String> getCurrencyFromSharedPreferences(String key) async {
|
||||
SharedPreferences prefs = await SharedPreferences.getInstance();
|
||||
if (prefs.getString(key)=="Euro"){
|
||||
_selectedCurrency="€";
|
||||
if (prefs.getString(key) == "Euro") {
|
||||
_selectedCurrency = "€";
|
||||
}
|
||||
if (prefs.getString(key)=="Dollar"){
|
||||
_selectedCurrency=r"$";
|
||||
if (prefs.getString(key) == "Dollar") {
|
||||
_selectedCurrency = r"$";
|
||||
}
|
||||
if (prefs.getString(key)=="CHF"){
|
||||
_selectedCurrency="CHF";
|
||||
if (prefs.getString(key) == "CHF") {
|
||||
_selectedCurrency = "CHF";
|
||||
}
|
||||
|
||||
return prefs.getString(key) ?? 'Euro';
|
||||
|
@ -77,9 +81,7 @@ class HomePageState extends State<HomePage> {
|
|||
super.initState();
|
||||
_themeManager.addListener(themeListener);
|
||||
getCurrencyFromSharedPreferences("currency").then((value) {
|
||||
setState(() {
|
||||
|
||||
});
|
||||
setState(() {});
|
||||
});
|
||||
loadAccounts();
|
||||
}
|
||||
|
@ -110,7 +112,7 @@ class HomePageState extends State<HomePage> {
|
|||
Future<void> saveAccounts() async {
|
||||
SharedPreferences prefs = await SharedPreferences.getInstance();
|
||||
List<String> accountJsonList =
|
||||
accounts.map((account) => json.encode(account.toJson())).toList();
|
||||
accounts.map((account) => json.encode(account.toJson())).toList();
|
||||
await prefs.setStringList('accounts', accountJsonList);
|
||||
}
|
||||
|
||||
|
@ -134,26 +136,35 @@ class HomePageState extends State<HomePage> {
|
|||
});
|
||||
}
|
||||
|
||||
Future<void> saveCurrencyToSharedPreferences(String key, String value) async {
|
||||
SharedPreferences prefs = await SharedPreferences.getInstance();
|
||||
await prefs.setString(key, value);
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
toolbarHeight: 70,
|
||||
centerTitle: true,
|
||||
backgroundColor: Colors.transparent,
|
||||
elevation: 0,
|
||||
title: Text(
|
||||
'title'.tr(),
|
||||
style: const TextStyle(
|
||||
fontSize: 18,
|
||||
fontWeight: FontWeight.bold,
|
||||
color: Colors.black54,
|
||||
),
|
||||
style: TextStyle(
|
||||
fontSize: 18,
|
||||
fontWeight: FontWeight.bold,
|
||||
color: Theme
|
||||
.of(context)
|
||||
.brightness == Brightness.dark
|
||||
? Colors.white70
|
||||
: Colors.black87),
|
||||
),
|
||||
actions: [
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(right: 16.0, top: 2, bottom: 0),
|
||||
padding: const EdgeInsets.only(right: 16.0, top: 9, bottom: 0),
|
||||
child: NeumorphicButton(
|
||||
margin: EdgeInsets.only(bottom: 10),
|
||||
margin: const EdgeInsets.only(bottom: 16),
|
||||
onPressed: () async {
|
||||
await Navigator.push(
|
||||
context,
|
||||
|
@ -164,67 +175,111 @@ class HomePageState extends State<HomePage> {
|
|||
style: NeumorphicStyle(
|
||||
shape: NeumorphicShape.convex,
|
||||
boxShape: const NeumorphicBoxShape.circle(),
|
||||
depth: 6,
|
||||
depth: 8,
|
||||
intensity: 0.9,
|
||||
color: Colors.grey.shade100,
|
||||
shadowLightColor:
|
||||
Theme
|
||||
.of(context)
|
||||
.brightness == Brightness.light
|
||||
? const NeumorphicStyle().shadowLightColor
|
||||
: Theme
|
||||
.of(context)
|
||||
.shadowColor,
|
||||
shadowDarkColor:
|
||||
Theme
|
||||
.of(context)
|
||||
.brightness == Brightness.dark
|
||||
? const NeumorphicStyle().shadowDarkColor
|
||||
: grey400,
|
||||
color: Theme
|
||||
.of(context)
|
||||
.brightness == Brightness.light
|
||||
? grey200
|
||||
: grey800,
|
||||
),
|
||||
child: const Icon(Icons.settings, color: Colors.black38),
|
||||
child: Icon(Icons.settings,
|
||||
color: Theme
|
||||
.of(context)
|
||||
.unselectedWidgetColor),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
body: ListView.builder(
|
||||
physics: const BouncingScrollPhysics(),
|
||||
itemCount: accounts.length,
|
||||
itemBuilder: (context, index) {
|
||||
return GestureDetector(
|
||||
onLongPress: () {
|
||||
AwesomeDialog(
|
||||
btnOkText: "Delete".tr(),
|
||||
btnOkColor: Colors.lightGreen,
|
||||
btnCancelColor: Colors.grey,
|
||||
context: context,
|
||||
animType: AnimType.bottomSlide,
|
||||
dialogType: DialogType.info,
|
||||
title: 'deleteaccount'.tr(),
|
||||
headerAnimationLoop: false,
|
||||
desc: 'sure'.tr(),
|
||||
btnCancelOnPress: () {},
|
||||
btnOkOnPress: () {
|
||||
deleteAccount(accounts[index]);
|
||||
body: Padding(
|
||||
padding: const EdgeInsets.only(top: 5),
|
||||
child: ListView.builder(
|
||||
physics: const BouncingScrollPhysics(),
|
||||
itemCount: accounts.length,
|
||||
itemBuilder: (context, index) {
|
||||
return GestureDetector(
|
||||
onLongPress: () {
|
||||
AwesomeDialog(
|
||||
btnOkText: "Delete".tr(),
|
||||
btnOkColor: Colors.lightGreen,
|
||||
btnCancelColor: Theme
|
||||
.of(context)
|
||||
.shadowColor,
|
||||
context: context,
|
||||
animType: AnimType.bottomSlide,
|
||||
dialogType: DialogType.info,
|
||||
title: 'deleteaccount'.tr(),
|
||||
headerAnimationLoop: false,
|
||||
desc: 'sure'.tr(),
|
||||
btnCancelOnPress: () {},
|
||||
btnOkOnPress: () {
|
||||
deleteAccount(accounts[index]);
|
||||
},
|
||||
).show();
|
||||
},
|
||||
).show();
|
||||
},
|
||||
child: Neumorphic(
|
||||
margin: const EdgeInsets.all(16),
|
||||
style: NeumorphicStyle(
|
||||
depth: 7,
|
||||
intensity: 1,
|
||||
shadowDarkColor: Colors.grey.shade300,
|
||||
color: Colors.grey.shade100,
|
||||
boxShape:
|
||||
child: Neumorphic(
|
||||
margin: const EdgeInsets.all(16),
|
||||
style: NeumorphicStyle(
|
||||
depth: 8,
|
||||
intensity: 1,
|
||||
shadowLightColor:
|
||||
Theme
|
||||
.of(context)
|
||||
.brightness == Brightness.light
|
||||
? const NeumorphicStyle().shadowLightColor
|
||||
: grey800,
|
||||
shadowDarkColor:
|
||||
Theme
|
||||
.of(context)
|
||||
.brightness == Brightness.dark
|
||||
? const NeumorphicStyle().shadowDarkColor
|
||||
: Theme
|
||||
.of(context)
|
||||
.shadowColor,
|
||||
color: Theme
|
||||
.of(context)
|
||||
.brightness == Brightness.light
|
||||
? grey200
|
||||
: grey800,
|
||||
boxShape:
|
||||
NeumorphicBoxShape.roundRect(BorderRadius.circular(15)),
|
||||
),
|
||||
child: ListTile(
|
||||
title: Text(accounts[index].name),
|
||||
subtitle: Text(
|
||||
'${'balance'.tr()}: $_selectedCurrency${accounts[index].balance.toStringAsFixed(2)}'),
|
||||
onTap: () {
|
||||
Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
builder: (context) => AccountDetailPage(
|
||||
account: accounts[index],
|
||||
updateAccountBalance: updateAccountBalance,
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
child: ListTile(
|
||||
title: Text(accounts[index].name),
|
||||
subtitle: Text(
|
||||
'${'balance'.tr()}: $_selectedCurrency${accounts[index]
|
||||
.balance.toStringAsFixed(2)}'),
|
||||
onTap: () {
|
||||
Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
builder: (context) =>
|
||||
AccountDetailPage(
|
||||
account: accounts[index],
|
||||
updateAccountBalance: updateAccountBalance,
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
)),
|
||||
floatingActionButton: NeumorphicButton(
|
||||
onPressed: () {
|
||||
showDialog(
|
||||
|
@ -239,14 +294,33 @@ class HomePageState extends State<HomePage> {
|
|||
style: NeumorphicStyle(
|
||||
depth: 8,
|
||||
intensity: 1,
|
||||
shadowDarkColor: Colors.grey.shade400,
|
||||
color: Colors.grey.shade100,
|
||||
shadowLightColor: Theme
|
||||
.of(context)
|
||||
.brightness == Brightness.light
|
||||
? const NeumorphicStyle().shadowLightColor
|
||||
: Theme
|
||||
.of(context)
|
||||
.shadowColor,
|
||||
shadowDarkColor: Theme
|
||||
.of(context)
|
||||
.brightness == Brightness.dark
|
||||
? const NeumorphicStyle().shadowDarkColor
|
||||
: grey400,
|
||||
color: Theme
|
||||
.of(context)
|
||||
.brightness == Brightness.light
|
||||
? grey200
|
||||
: grey800,
|
||||
boxShape: const NeumorphicBoxShape.circle(),
|
||||
),
|
||||
child: const Icon(
|
||||
child: Icon(
|
||||
Icons.add,
|
||||
size: 60,
|
||||
color: Colors.black12,
|
||||
color: Theme
|
||||
.of(context)
|
||||
.brightness == Brightness.light
|
||||
? Colors.black12
|
||||
: Colors.white12,
|
||||
),
|
||||
),
|
||||
);
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
import 'dart:async';
|
||||
|
||||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter_neumorphic/flutter_neumorphic.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
import 'package:tests/theme/theme_constants.dart';
|
||||
import 'package:tests/theme/theme_manager.dart';
|
||||
|
||||
import 'main.dart';
|
||||
|
||||
ThemeManager _themeManager = ThemeManager();
|
||||
|
@ -50,6 +50,11 @@ class SettingsState extends State<Settings> {
|
|||
await prefs.setString(key, value);
|
||||
}
|
||||
|
||||
Future<void> saveThemeToSharedPreferences(String key, bool value) async {
|
||||
SharedPreferences prefs = await SharedPreferences.getInstance();
|
||||
await prefs.setBool(key, value);
|
||||
}
|
||||
|
||||
Future<String> getCurrencyFromSharedPreferences(String key) async {
|
||||
SharedPreferences prefs = await SharedPreferences.getInstance();
|
||||
return prefs.getString(key) ?? 'Euro';
|
||||
|
@ -84,11 +89,12 @@ class SettingsState extends State<Settings> {
|
|||
toolbarHeight: 80,
|
||||
title: Text(
|
||||
'settings'.tr(),
|
||||
style: const TextStyle(
|
||||
fontSize: 18,
|
||||
fontWeight: FontWeight.bold,
|
||||
color: Colors.black54,
|
||||
),
|
||||
style: TextStyle(
|
||||
fontSize: 18,
|
||||
fontWeight: FontWeight.bold,
|
||||
color: Theme.of(context).brightness == Brightness.dark
|
||||
? Colors.white70
|
||||
: Colors.black87),
|
||||
),
|
||||
centerTitle: true,
|
||||
shape: const RoundedRectangleBorder(
|
||||
|
@ -97,13 +103,14 @@ class SettingsState extends State<Settings> {
|
|||
bottomRight: Radius.circular(15),
|
||||
),
|
||||
),
|
||||
shadowColor: Colors.grey.shade300,
|
||||
shadowColor: Theme.of(context).shadowColor,
|
||||
leading: Padding(
|
||||
padding: const EdgeInsets.only(left: 16.0),
|
||||
child: NeumorphicButton(
|
||||
onPressed: () {
|
||||
Navigator.pop(context); // Zurück zur vorherigen Seite
|
||||
Navigator.pushReplacement( // Neue Seite öffnen und vorherige Seite ersetzen
|
||||
Navigator.pushReplacement(
|
||||
// Neue Seite öffnen und vorherige Seite ersetzen
|
||||
context,
|
||||
MaterialPageRoute(builder: (context) => const HomePage()),
|
||||
);
|
||||
|
@ -111,12 +118,21 @@ class SettingsState extends State<Settings> {
|
|||
style: NeumorphicStyle(
|
||||
shape: NeumorphicShape.flat,
|
||||
boxShape: const NeumorphicBoxShape.circle(),
|
||||
depth: 6,
|
||||
depth: 7,
|
||||
intensity: 0.9,
|
||||
color: Colors.grey.shade100,
|
||||
shadowLightColor: Theme.of(context).brightness == Brightness.light
|
||||
? const NeumorphicStyle().shadowLightColor
|
||||
: Theme.of(context).shadowColor,
|
||||
shadowDarkColor: Theme.of(context).brightness == Brightness.dark
|
||||
? const NeumorphicStyle().shadowDarkColor
|
||||
: grey400,
|
||||
color: Theme.of(context).brightness == Brightness.light
|
||||
? grey200
|
||||
: grey800,
|
||||
),
|
||||
padding: const EdgeInsets.all(10),
|
||||
child: const Icon(Icons.arrow_back, color: Colors.black38),
|
||||
padding: const EdgeInsets.all(8),
|
||||
child: Icon(Icons.arrow_back,
|
||||
color: Theme.of(context).unselectedWidgetColor),
|
||||
),
|
||||
),
|
||||
),
|
||||
|
@ -127,38 +143,57 @@ class SettingsState extends State<Settings> {
|
|||
style: NeumorphicStyle(
|
||||
depth: 7,
|
||||
intensity: 1,
|
||||
shadowDarkColor: Colors.grey.shade300,
|
||||
color: Colors.grey.shade100,
|
||||
shadowLightColor: Theme.of(context).brightness == Brightness.light
|
||||
? const NeumorphicStyle().shadowLightColor
|
||||
: grey800,
|
||||
shadowDarkColor: Theme.of(context).brightness == Brightness.dark
|
||||
? const NeumorphicStyle().shadowDarkColor
|
||||
: Theme.of(context).shadowColor,
|
||||
color: Theme.of(context).brightness == Brightness.light
|
||||
? grey200
|
||||
: grey800,
|
||||
boxShape: NeumorphicBoxShape.roundRect(BorderRadius.circular(15)),
|
||||
),
|
||||
child: ListTile(
|
||||
title: Text('darkmode'.tr()),
|
||||
trailing: NeumorphicSwitch(
|
||||
value: _themeManager.themeMode == ThemeMode.dark,
|
||||
onChanged: (bool value) {
|
||||
setState(() {
|
||||
_themeManager.toggleTheme(value);
|
||||
});
|
||||
},
|
||||
style: NeumorphicSwitchStyle(
|
||||
lightSource: LightSource.topLeft,
|
||||
thumbShape: NeumorphicShape.concave,
|
||||
trackDepth: 5,
|
||||
activeTrackColor: Colors.lightGreen,
|
||||
inactiveTrackColor: Colors.grey.shade300,
|
||||
activeThumbColor: Colors.grey.shade100,
|
||||
inactiveThumbColor: Colors.grey.shade200,
|
||||
),
|
||||
),
|
||||
),
|
||||
title: Text('darkmode'.tr()),
|
||||
trailing:
|
||||
Consumer<ThemeManager>(builder: (context, themeManager, _) {
|
||||
return NeumorphicSwitch(
|
||||
value: themeManager.themeMode == ThemeMode.dark,
|
||||
onChanged: (bool value) {
|
||||
setState(() {
|
||||
themeManager.toggleTheme(value);
|
||||
});
|
||||
},
|
||||
style: NeumorphicSwitchStyle(
|
||||
lightSource: LightSource.topLeft,
|
||||
thumbShape: NeumorphicShape.concave,
|
||||
trackDepth: 5,
|
||||
activeTrackColor: Colors.lightGreen,
|
||||
inactiveTrackColor: Theme.of(context).shadowColor,
|
||||
activeThumbColor:
|
||||
Theme.of(context).brightness == Brightness.light
|
||||
? grey200
|
||||
: grey800,
|
||||
inactiveThumbColor: Theme.of(context).shadowColor,
|
||||
),
|
||||
);
|
||||
})),
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
Neumorphic(
|
||||
style: NeumorphicStyle(
|
||||
depth: 7,
|
||||
intensity: 1,
|
||||
shadowDarkColor: Colors.grey.shade300,
|
||||
color: Colors.grey.shade100,
|
||||
shadowLightColor: Theme.of(context).brightness == Brightness.light
|
||||
? const NeumorphicStyle().shadowLightColor
|
||||
: grey800,
|
||||
shadowDarkColor: Theme.of(context).brightness == Brightness.dark
|
||||
? const NeumorphicStyle().shadowDarkColor
|
||||
: Theme.of(context).shadowColor,
|
||||
color: Theme.of(context).brightness == Brightness.light
|
||||
? grey200
|
||||
: grey800,
|
||||
boxShape: NeumorphicBoxShape.roundRect(BorderRadius.circular(15)),
|
||||
),
|
||||
child: ListTile(
|
||||
|
@ -196,8 +231,15 @@ class SettingsState extends State<Settings> {
|
|||
style: NeumorphicStyle(
|
||||
depth: 7,
|
||||
intensity: 1,
|
||||
shadowDarkColor: Colors.grey.shade300,
|
||||
color: Colors.grey.shade100,
|
||||
shadowLightColor: Theme.of(context).brightness == Brightness.light
|
||||
? const NeumorphicStyle().shadowLightColor
|
||||
: grey800,
|
||||
shadowDarkColor: Theme.of(context).brightness == Brightness.dark
|
||||
? const NeumorphicStyle().shadowDarkColor
|
||||
: Theme.of(context).shadowColor,
|
||||
color: Theme.of(context).brightness == Brightness.light
|
||||
? grey200
|
||||
: grey800,
|
||||
boxShape: NeumorphicBoxShape.roundRect(BorderRadius.circular(15)),
|
||||
),
|
||||
child: ListTile(
|
||||
|
@ -211,10 +253,12 @@ class SettingsState extends State<Settings> {
|
|||
onChanged: (String? newValue) {
|
||||
setState(() {
|
||||
_selectedCurrency = newValue!;
|
||||
saveCurrencyToSharedPreferences("currency", _selectedCurrency);
|
||||
saveCurrencyToSharedPreferences(
|
||||
"currency", _selectedCurrency);
|
||||
});
|
||||
},
|
||||
items: _currencies.map<DropdownMenuItem<String>>((String value) {
|
||||
items:
|
||||
_currencies.map<DropdownMenuItem<String>>((String value) {
|
||||
return DropdownMenuItem<String>(
|
||||
value: value,
|
||||
child: Text(value),
|
||||
|
|
|
@ -1,24 +1,26 @@
|
|||
import 'package:carousel_slider/carousel_slider.dart';
|
||||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:flutter_neumorphic/flutter_neumorphic.dart';
|
||||
import 'package:tests/theme/theme_constants.dart';
|
||||
|
||||
class SavingsTipsDialog extends StatelessWidget {
|
||||
final List<String> savingsTips = [
|
||||
'Spare jeden Monat einen festen Betrag.',
|
||||
'Vergleiche Preise, bevor du etwas kaufst.',
|
||||
'Vermeide unnötige Ausgaben.',
|
||||
'Setze dir konkrete Sparziele.',
|
||||
'Überprüfe regelmäßig deine Ausgaben.',
|
||||
'Verkaufe Dinge, die du nicht mehr brauchst.',
|
||||
'Nutze Cashback-Programme beim Einkaufen.',
|
||||
'Koche selbst anstatt auswärts zu essen.',
|
||||
'Nutze kostenlose Angebote und Gutscheine.',
|
||||
'Vermeide Impulskäufe und schlafe vor größeren Ausgaben eine Nacht darüber.',
|
||||
'Fahre mit dem Fahrrad oder öffentlichen Verkehrsmitteln anstatt mit dem Auto.',
|
||||
'Plane deine Mahlzeiten im Voraus, um Lebensmittelverschwendung zu vermeiden.',
|
||||
'Vergleiche Versicherungen und Verträge, um Geld zu sparen.',
|
||||
'Mache deine eigenen Reinigungsmittel statt teure Produkte zu kaufen.',
|
||||
'Nutze kostenlose Online-Ressourcen für Weiterbildung und Hobbys.',
|
||||
'tip1'.tr(),
|
||||
'tip2'.tr(),
|
||||
'tip3'.tr(),
|
||||
'tip4'.tr(),
|
||||
'tip5'.tr(),
|
||||
'tip6'.tr(),
|
||||
'tip7'.tr(),
|
||||
'tip8'.tr(),
|
||||
'tip9'.tr(),
|
||||
'tip10'.tr(),
|
||||
'tip11'.tr(),
|
||||
'tip12'.tr(),
|
||||
'tip13'.tr(),
|
||||
'tip14'.tr(),
|
||||
'tip15'.tr(),
|
||||
|
||||
];
|
||||
|
||||
SavingsTipsDialog({super.key});
|
||||
|
@ -38,30 +40,40 @@ class SavingsTipsDialog extends StatelessWidget {
|
|||
itemCount: savingsTips.length,
|
||||
itemBuilder: (BuildContext context, int index, int realIndex) {
|
||||
return Neumorphic(
|
||||
margin: const EdgeInsets.only(bottom: 5),
|
||||
style: NeumorphicStyle(
|
||||
boxShape: NeumorphicBoxShape.roundRect(
|
||||
BorderRadius.circular(13.0)),
|
||||
),
|
||||
child: Container(
|
||||
decoration: BoxDecoration(
|
||||
margin: const EdgeInsets.fromLTRB(0, 11, 0, 7),
|
||||
style: NeumorphicStyle(
|
||||
shadowLightColor:
|
||||
Theme.of(context).brightness == Brightness.light
|
||||
? const NeumorphicStyle().shadowLightColor
|
||||
: Theme.of(context).shadowColor,
|
||||
shadowDarkColor:
|
||||
Theme.of(context).brightness == Brightness.dark
|
||||
? const NeumorphicStyle().shadowDarkColor
|
||||
: grey400,
|
||||
color: Theme.of(context).brightness == Brightness.light
|
||||
? grey200
|
||||
: grey800,
|
||||
boxShape: NeumorphicBoxShape.roundRect(
|
||||
BorderRadius.circular(13.0)),
|
||||
),
|
||||
child: Container(
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(10.0),
|
||||
color: Colors.grey
|
||||
.shade100, // Setze die Hintergrundfarbe auf rot
|
||||
),
|
||||
padding: const EdgeInsets.all(14.0),
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Text(
|
||||
savingsTips[index],
|
||||
style: const TextStyle(fontSize: 18.0),
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
],
|
||||
),
|
||||
color: Theme.of(context).brightness == Brightness.dark
|
||||
? grey700
|
||||
: grey200),
|
||||
padding: const EdgeInsets.all(14.0),
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Text(
|
||||
savingsTips[index],
|
||||
style: const TextStyle(fontSize: 18.0),
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
],
|
||||
),
|
||||
|
||||
),
|
||||
);
|
||||
},
|
||||
options: CarouselOptions(
|
||||
|
@ -83,14 +95,26 @@ class SavingsTipsDialog extends StatelessWidget {
|
|||
Navigator.of(context).pop();
|
||||
},
|
||||
style: NeumorphicStyle(
|
||||
color: Colors.grey.shade100,
|
||||
shadowLightColor:
|
||||
Theme.of(context).brightness == Brightness.light
|
||||
? const NeumorphicStyle().shadowLightColor
|
||||
: Theme.of(context).shadowColor,
|
||||
shadowDarkColor: Theme.of(context).brightness == Brightness.dark
|
||||
? const NeumorphicStyle().shadowDarkColor
|
||||
: grey400,
|
||||
color: Theme.of(context).brightness == Brightness.light
|
||||
? grey200
|
||||
: grey800,
|
||||
depth: 10,
|
||||
intensity: 0.9,
|
||||
shape: NeumorphicShape.flat,
|
||||
boxShape:
|
||||
NeumorphicBoxShape.roundRect(BorderRadius.circular(15.0)),
|
||||
),
|
||||
child: Text('close'.tr()),
|
||||
child: Text(
|
||||
'close'.tr(),
|
||||
style: TextStyle(color: Theme.of(context).cardColor),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
|
|
|
@ -1,17 +1,66 @@
|
|||
import 'package:flutter/material.dart';
|
||||
|
||||
const COLOR_PRIMARY = Colors.deepOrangeAccent;
|
||||
|
||||
ThemeData lightTheme = ThemeData(
|
||||
brightness: Brightness.light,
|
||||
primaryColor: COLOR_PRIMARY,
|
||||
fontFamily: "Montserrat");
|
||||
|
||||
ThemeData darkTheme = ThemeData(
|
||||
fontFamily: "Montserrat",
|
||||
brightness: Brightness.dark,
|
||||
switchTheme: SwitchThemeData(
|
||||
trackColor: MaterialStateProperty.all<Color>(Colors.grey),
|
||||
thumbColor: MaterialStateProperty.all<Color>(Colors.white),
|
||||
final grey200=Colors.grey[200];
|
||||
final grey300=Colors.grey[300];
|
||||
final grey400=Colors.grey[400];
|
||||
final grey700=Colors.grey[700];
|
||||
final grey800=Colors.grey[800];
|
||||
final grey600=Colors.grey[600];
|
||||
final ThemeData lightTheme = ThemeData(
|
||||
scaffoldBackgroundColor: Colors.grey[100],
|
||||
textTheme: const TextTheme(
|
||||
displayLarge:(TextStyle(color: Colors.black87)),
|
||||
displayMedium: (TextStyle(color: Colors.black87)),
|
||||
displaySmall:(TextStyle(color: Colors.black87)),
|
||||
labelLarge:(TextStyle(color: Colors.black87)),
|
||||
labelMedium:(TextStyle(color: Colors.black87)),
|
||||
labelSmall:(TextStyle(color: Colors.black87)),
|
||||
headlineLarge:(TextStyle(color: Colors.black87)),
|
||||
headlineMedium:(TextStyle(color: Colors.black87)),
|
||||
headlineSmall:(TextStyle(color: Colors.black87)),
|
||||
titleLarge:(TextStyle(color: Colors.black87)),
|
||||
titleMedium:(TextStyle(color: Colors.black87)),
|
||||
titleSmall:(TextStyle(color: Colors.black87)),
|
||||
bodyLarge: (TextStyle(color: Colors.black54)),
|
||||
bodyMedium:(TextStyle(color: Colors.black54)),
|
||||
bodySmall: (TextStyle(color: Colors.black54))
|
||||
),
|
||||
brightness: Brightness.light,
|
||||
shadowColor: Colors.grey[300],
|
||||
cardColor: Colors.black87,
|
||||
unselectedWidgetColor: Colors.black54,
|
||||
fontFamily: "Montserrat",
|
||||
buttonTheme: ButtonThemeData(
|
||||
buttonColor: Colors.grey[100],
|
||||
textTheme: ButtonTextTheme.primary
|
||||
),
|
||||
|
||||
);
|
||||
|
||||
final ThemeData darkTheme = ThemeData(
|
||||
textTheme: const TextTheme(
|
||||
displayLarge:(TextStyle(color: Colors.white70)),
|
||||
displayMedium: (TextStyle(color: Colors.white70)),
|
||||
displaySmall:(TextStyle(color: Colors.white70)),
|
||||
labelLarge:(TextStyle(color: Colors.white70)),
|
||||
labelMedium:(TextStyle(color: Colors.white70)),
|
||||
labelSmall:(TextStyle(color: Colors.white70)),
|
||||
headlineLarge:(TextStyle(color: Colors.white70)),
|
||||
headlineMedium:(TextStyle(color: Colors.white70)),
|
||||
headlineSmall:(TextStyle(color: Colors.white70)),
|
||||
titleLarge:(TextStyle(color: Colors.white70)),
|
||||
titleMedium:(TextStyle(color: Colors.white70)),
|
||||
titleSmall:(TextStyle(color: Colors.white70)),
|
||||
bodyLarge: (TextStyle(color: Colors.white54)),
|
||||
bodyMedium:(TextStyle(color: Colors.white54)),
|
||||
bodySmall: (TextStyle(color: Colors.white54)),
|
||||
),
|
||||
shadowColor: Colors.grey[700],
|
||||
fontFamily: "Montserrat",
|
||||
cardColor: Colors.white70,
|
||||
unselectedWidgetColor: Colors.white54,
|
||||
brightness: Brightness.dark,
|
||||
buttonTheme: ButtonThemeData(
|
||||
buttonColor: Colors.grey[900],
|
||||
),
|
||||
);
|
|
@ -1,14 +1,13 @@
|
|||
import 'package:flutter/material.dart';
|
||||
|
||||
class ThemeManager with ChangeNotifier{
|
||||
|
||||
class ThemeManager with ChangeNotifier {
|
||||
ThemeMode _themeMode = ThemeMode.light;
|
||||
|
||||
get themeMode => _themeMode;
|
||||
ThemeMode get themeMode => _themeMode;
|
||||
|
||||
toggleTheme(bool isDark){
|
||||
_themeMode = isDark?ThemeMode.dark:ThemeMode.light;
|
||||
void toggleTheme(bool isDark) {
|
||||
_themeMode = isDark ? ThemeMode.dark : ThemeMode.light;
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -1,9 +1,11 @@
|
|||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:flutter_neumorphic/flutter_neumorphic.dart';
|
||||
import 'package:tests/transaction/transaction.dart';
|
||||
import '../theme/theme_constants.dart';
|
||||
|
||||
class AddTransactionDialog extends StatefulWidget {
|
||||
final Function addTransaction;
|
||||
|
||||
const AddTransactionDialog({super.key, required this.addTransaction});
|
||||
|
||||
@override
|
||||
|
@ -48,11 +50,10 @@ class AddTransactionDialogState extends State<AddTransactionDialog> {
|
|||
'addtrans'.tr(),
|
||||
style: const TextStyle(
|
||||
fontSize: 20,
|
||||
color: Colors.black54,
|
||||
),
|
||||
),
|
||||
content: Form(
|
||||
key: _formKey, // Hier wird das _formKey dem Form-Widget zugewiesen
|
||||
key: _formKey, //
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
|
@ -60,7 +61,17 @@ class AddTransactionDialogState extends State<AddTransactionDialog> {
|
|||
style: NeumorphicStyle(
|
||||
depth: -5,
|
||||
intensity: 0.8,
|
||||
color: Colors.grey.shade100,
|
||||
shadowLightColor:
|
||||
Theme.of(context).brightness == Brightness.light
|
||||
? const NeumorphicStyle().shadowLightColor
|
||||
: Theme.of(context).shadowColor,
|
||||
shadowDarkColor:
|
||||
Theme.of(context).brightness == Brightness.dark
|
||||
? const NeumorphicStyle().shadowDarkColor
|
||||
: grey400,
|
||||
color: Theme.of(context).brightness == Brightness.light
|
||||
? grey200
|
||||
: grey800,
|
||||
boxShape: NeumorphicBoxShape.roundRect(
|
||||
BorderRadius.circular(12),
|
||||
),
|
||||
|
@ -88,7 +99,17 @@ class AddTransactionDialogState extends State<AddTransactionDialog> {
|
|||
style: NeumorphicStyle(
|
||||
depth: -5,
|
||||
intensity: 0.8,
|
||||
color: Colors.grey.shade100,
|
||||
shadowLightColor:
|
||||
Theme.of(context).brightness == Brightness.light
|
||||
? const NeumorphicStyle().shadowLightColor
|
||||
: Theme.of(context).shadowColor,
|
||||
shadowDarkColor:
|
||||
Theme.of(context).brightness == Brightness.dark
|
||||
? const NeumorphicStyle().shadowDarkColor
|
||||
: grey400,
|
||||
color: Theme.of(context).brightness == Brightness.light
|
||||
? grey200
|
||||
: grey800,
|
||||
boxShape: NeumorphicBoxShape.roundRect(
|
||||
BorderRadius.circular(12),
|
||||
),
|
||||
|
@ -121,7 +142,10 @@ class AddTransactionDialogState extends State<AddTransactionDialog> {
|
|||
NeumorphicCheckbox(
|
||||
style: NeumorphicCheckboxStyle(
|
||||
selectedColor: Colors.lightGreen,
|
||||
disabledColor: Colors.grey.shade200,
|
||||
disabledColor:
|
||||
Theme.of(context).brightness == Brightness.light
|
||||
? grey200
|
||||
: grey800,
|
||||
selectedDepth: -10,
|
||||
unselectedDepth: 8),
|
||||
value: _isExpense,
|
||||
|
@ -134,7 +158,6 @@ class AddTransactionDialogState extends State<AddTransactionDialog> {
|
|||
const SizedBox(width: 8),
|
||||
Text(
|
||||
'expense'.tr(),
|
||||
style: const TextStyle(color: Colors.black87),
|
||||
),
|
||||
],
|
||||
),
|
||||
|
@ -152,7 +175,15 @@ class AddTransactionDialogState extends State<AddTransactionDialog> {
|
|||
boxShape: NeumorphicBoxShape.roundRect(
|
||||
BorderRadius.circular(12),
|
||||
),
|
||||
color: Colors.grey.shade100,
|
||||
shadowLightColor: Theme.of(context).brightness == Brightness.light
|
||||
? const NeumorphicStyle().shadowLightColor
|
||||
: Theme.of(context).shadowColor,
|
||||
shadowDarkColor: Theme.of(context).brightness == Brightness.dark
|
||||
? const NeumorphicStyle().shadowDarkColor
|
||||
: grey400,
|
||||
color: Theme.of(context).brightness == Brightness.light
|
||||
? grey200
|
||||
: grey800,
|
||||
),
|
||||
padding: const EdgeInsets.symmetric(vertical: 12, horizontal: 16),
|
||||
child: Text(
|
||||
|
@ -164,6 +195,7 @@ class AddTransactionDialogState extends State<AddTransactionDialog> {
|
|||
),
|
||||
),
|
||||
NeumorphicButton(
|
||||
margin: const EdgeInsets.fromLTRB(0, 0, 4, 4),
|
||||
onPressed: _submitForm,
|
||||
style: NeumorphicStyle(
|
||||
shape: NeumorphicShape.concave,
|
||||
|
@ -172,7 +204,15 @@ class AddTransactionDialogState extends State<AddTransactionDialog> {
|
|||
boxShape: NeumorphicBoxShape.roundRect(
|
||||
BorderRadius.circular(12),
|
||||
),
|
||||
color: Colors.grey.shade100,
|
||||
shadowLightColor: Theme.of(context).brightness == Brightness.light
|
||||
? const NeumorphicStyle().shadowLightColor
|
||||
: Theme.of(context).shadowColor,
|
||||
shadowDarkColor: Theme.of(context).brightness == Brightness.dark
|
||||
? const NeumorphicStyle().shadowDarkColor
|
||||
: grey400,
|
||||
color: Theme.of(context).brightness == Brightness.light
|
||||
? grey200
|
||||
: grey800,
|
||||
),
|
||||
padding: const EdgeInsets.symmetric(vertical: 12, horizontal: 16),
|
||||
child: Text(
|
||||
|
|
16
pubspec.lock
16
pubspec.lock
|
@ -261,6 +261,14 @@ packages:
|
|||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.8.0"
|
||||
nested:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: nested
|
||||
sha256: "03bac4c528c64c95c722ec99280375a6f2fc708eec17c7b3f07253b626cd2a20"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.0.0"
|
||||
path:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -333,6 +341,14 @@ packages:
|
|||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "4.2.4"
|
||||
provider:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: provider
|
||||
sha256: cdbe7530b12ecd9eb455bdaa2fcb8d4dad22e80b8afb4798b41479d5ce26847f
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "6.0.5"
|
||||
rive:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
|
|
@ -44,6 +44,7 @@ dependencies:
|
|||
flutter_svg: ^2.0.0
|
||||
circular_seek_bar: ^1.1.0
|
||||
tab_indicator_styler: ^2.0.0
|
||||
provider: ^6.0.5
|
||||
|
||||
dev_dependencies:
|
||||
flutter_test:
|
||||
|
|
Loading…
Reference in New Issue