Darkmode+ budgetchecker finished

main
Arlind 2023-06-17 03:09:31 +02:00
parent 5582e7b4fa
commit db9abf9866
13 changed files with 727 additions and 283 deletions

View File

@ -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';
@ -46,19 +47,25 @@ class AccountDetailPageState extends State<AccountDetailPage>
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(
style: TextStyle(
fontSize: 18,
fontWeight: FontWeight.bold,
color: Colors.black54,
),
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,
@ -351,23 +419,58 @@ class AccountDetailPageState extends State<AccountDetailPage>
child: Center(
child: ValueListenableBuilder(
valueListenable: _valueNotifier,
builder: (_, double value, __) => Column(
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),
),
Text(
'progress'.tr(),
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),

View File

@ -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(

View File

@ -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"
}

View File

@ -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"
}

View File

@ -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),

View File

@ -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,13 +16,15 @@ Future<void> main() async {
WidgetsFlutterBinding.ensureInitialized();
await EasyLocalization.ensureInitialized();
runApp(
EasyLocalization(
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(),
);
}
@ -77,9 +81,7 @@ class HomePageState extends State<HomePage> {
super.initState();
_themeManager.addListener(themeListener);
getCurrencyFromSharedPreferences("currency").then((value) {
setState(() {
});
setState(() {});
});
loadAccounts();
}
@ -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(
style: TextStyle(
fontSize: 18,
fontWeight: FontWeight.bold,
color: Colors.black54,
),
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,16 +175,39 @@ 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(
body: Padding(
padding: const EdgeInsets.only(top: 5),
child: ListView.builder(
physics: const BouncingScrollPhysics(),
itemCount: accounts.length,
itemBuilder: (context, index) {
@ -182,7 +216,9 @@ class HomePageState extends State<HomePage> {
AwesomeDialog(
btnOkText: "Delete".tr(),
btnOkColor: Colors.lightGreen,
btnCancelColor: Colors.grey,
btnCancelColor: Theme
.of(context)
.shadowColor,
context: context,
animType: AnimType.bottomSlide,
dialogType: DialogType.info,
@ -198,22 +234,41 @@ class HomePageState extends State<HomePage> {
child: Neumorphic(
margin: const EdgeInsets.all(16),
style: NeumorphicStyle(
depth: 7,
depth: 8,
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(accounts[index].name),
subtitle: Text(
'${'balance'.tr()}: $_selectedCurrency${accounts[index].balance.toStringAsFixed(2)}'),
'${'balance'.tr()}: $_selectedCurrency${accounts[index]
.balance.toStringAsFixed(2)}'),
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => AccountDetailPage(
builder: (context) =>
AccountDetailPage(
account: accounts[index],
updateAccountBalance: updateAccountBalance,
),
@ -224,7 +279,7 @@ class HomePageState extends State<HomePage> {
),
);
},
),
)),
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,
),
),
);

View File

@ -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(
style: TextStyle(
fontSize: 18,
fontWeight: FontWeight.bold,
color: Colors.black54,
),
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,17 +143,26 @@ 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,
trailing:
Consumer<ThemeManager>(builder: (context, themeManager, _) {
return NeumorphicSwitch(
value: themeManager.themeMode == ThemeMode.dark,
onChanged: (bool value) {
setState(() {
_themeManager.toggleTheme(value);
themeManager.toggleTheme(value);
});
},
style: NeumorphicSwitchStyle(
@ -145,20 +170,30 @@ class SettingsState extends State<Settings> {
thumbShape: NeumorphicShape.concave,
trackDepth: 5,
activeTrackColor: Colors.lightGreen,
inactiveTrackColor: Colors.grey.shade300,
activeThumbColor: Colors.grey.shade100,
inactiveThumbColor: Colors.grey.shade200,
),
),
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),

View File

@ -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,17 +40,28 @@ class SavingsTipsDialog extends StatelessWidget {
itemCount: savingsTips.length,
itemBuilder: (BuildContext context, int index, int realIndex) {
return Neumorphic(
margin: const EdgeInsets.only(bottom: 5),
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
),
color: Theme.of(context).brightness == Brightness.dark
? grey700
: grey200),
padding: const EdgeInsets.all(14.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
@ -61,7 +74,6 @@ class SavingsTipsDialog extends StatelessWidget {
],
),
),
);
},
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),
),
),
],
),

View File

@ -1,17 +1,66 @@
import 'package:flutter/material.dart';
const COLOR_PRIMARY = Colors.deepOrangeAccent;
ThemeData lightTheme = ThemeData(
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,
primaryColor: COLOR_PRIMARY,
fontFamily: "Montserrat");
ThemeData darkTheme = ThemeData(
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,
switchTheme: SwitchThemeData(
trackColor: MaterialStateProperty.all<Color>(Colors.grey),
thumbColor: MaterialStateProperty.all<Color>(Colors.white),
buttonTheme: ButtonThemeData(
buttonColor: Colors.grey[900],
),
);

View File

@ -1,14 +1,13 @@
import 'package:flutter/material.dart';
class ThemeManager with ChangeNotifier {
ThemeMode _themeMode = ThemeMode.light;
get themeMode => _themeMode;
ThemeMode get themeMode => _themeMode;
toggleTheme(bool isDark){
void toggleTheme(bool isDark) {
_themeMode = isDark ? ThemeMode.dark : ThemeMode.light;
notifyListeners();
}
}
}

View File

@ -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(

View File

@ -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:

View File

@ -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: