diff --git a/lib/Pages/Dashboard/dashboard.dart b/lib/Pages/Dashboard/dashboard.dart index 612f1a2..aa107c2 100644 --- a/lib/Pages/Dashboard/dashboard.dart +++ b/lib/Pages/Dashboard/dashboard.dart @@ -1,6 +1,239 @@ +import 'package:fl_chart/fl_chart.dart'; import 'package:flutter/material.dart'; +/// Eine Seite, die das Dashboard der App darstellt. +/// +/// Diese Seite zeigt eine Übersicht über den aktuellen Kontostand, +/// die Entwicklung des Kontostands der letzten Monate sowie +/// die letzten Transaktionen. class Dashboard extends StatelessWidget { + /// Erstellt eine neue Instanz der Dashboard-Seite. + const Dashboard({super.key}); + + /// Baut das Dashboard-Widget auf. + /// [context] ist der Build-Kontext @override - Widget build(final BuildContext context) => const Text('DASHBOARD'); + Widget build(final BuildContext context) { + const double currentBalance = 4820.75; + const double previousMonthBalance = 4300; + + final Map monthlyBalance = { + 'Jan': 1200.0, + 'Feb': 900.0, + 'Mär': 1100.0, + 'Apr': 950.0, + 'Mai': 1300.0, + 'Jun': 1050.0, + }; + + final List> recentTransactions = >[ + {'name': 'Supermarkt', 'amount': -45.50}, + {'name': 'Gehalt', 'amount': 2500.00}, + {'name': 'Miete', 'amount': -900.00}, + {'name': 'Streaming', 'amount': -12.99}, + {'name': 'Kaffee', 'amount': -4.50}, + ]; + + return Scaffold( + body: SafeArea( + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 24), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + _currentBalance(currentBalance, previousMonthBalance, context), + const SizedBox(height: 32), + + const Text( + 'Kontostand pro Monat', + style: TextStyle(fontSize: 20, fontWeight: FontWeight.bold), + ), + const SizedBox(height: 12), + _monthlyBalance(monthlyBalance, context), + + const SizedBox(height: 32), + const Text( + 'Letzte Transaktionen', + style: TextStyle(fontSize: 20, fontWeight: FontWeight.bold), + ), + const SizedBox(height: 12), + ..._recentTransactions(recentTransactions), + ], + ), + ), + ), + ); + } + + /// Baut das Widget für den aktuellen Kontostand + /// und die Differenz zum Vormonat auf. + /// + /// [currentBalance] ist der aktuelle Kontostand + /// [previousBalance] ist der Kontostand des Vormonats + /// [context] ist der Build-Kontext + Widget _currentBalance( + final double currentBalance, + final double previousBalance, + final BuildContext context, + ) { + final ThemeData theme = Theme.of(context); + + final double diff = currentBalance - previousBalance; + + return Container( + padding: const EdgeInsets.all(16), + decoration: BoxDecoration( + color: theme.colorScheme.primaryContainer, + borderRadius: BorderRadius.circular(16), + ), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text('Aktuell', style: theme.textTheme.bodyMedium), + const SizedBox(height: 8), + Text( + '${currentBalance.toStringAsFixed(2)} €', + style: theme.textTheme.headlineSmall?.copyWith( + fontWeight: FontWeight.bold, + ), + ), + ], + ), + + Column( + crossAxisAlignment: CrossAxisAlignment.end, + children: [ + Text( + 'Differenz zum Vormonat', + style: theme.textTheme.bodySmall?.copyWith( + color: theme.colorScheme.onSurface, + ), + ), + const SizedBox(height: 8), + Row( + children: [ + Icon( + diff >= 0 ? Icons.arrow_upward : Icons.arrow_downward, + color: diff >= 0 ? Colors.green : Colors.red, + ), + const SizedBox(width: 4), + Text( + '${diff.abs().toStringAsFixed(2)} €', + style: theme.textTheme.titleMedium?.copyWith( + fontWeight: FontWeight.bold, + color: diff >= 0 ? Colors.green : Colors.red, + ), + ), + ], + ), + ], + ), + ], + ), + ); + } + + /// Baut das Widget für die Entwicklung + /// des Kontostands der letzten Monate auf. + /// + /// [monthlyBalance] ist ein Map mit den Monaten als Schlüssel und + /// den dazugehörigen Kontoständen als Werte. + /// [context] ist der Build-Kontext. + Widget _monthlyBalance( + final Map monthlyBalance, + final BuildContext context, + ) { + final ThemeData theme = Theme.of(context); + final double maxY = + monthlyBalance.values.reduce( + (final double a, final double b) => a > b ? a : b, + ) + + 200; + + return SizedBox( + height: 180, + child: LineChart( + LineChartData( + minY: 0, + maxY: maxY, + titlesData: FlTitlesData( + topTitles: const AxisTitles(), + rightTitles: const AxisTitles(), + bottomTitles: AxisTitles( + sideTitles: SideTitles( + showTitles: true, + reservedSize: 28, + interval: 1, + getTitlesWidget: (final double value, final TitleMeta meta) { + final List months = monthlyBalance.keys.toList(); + if (value.toInt() >= 0 && value.toInt() < months.length) { + return Text(months[value.toInt()]); + } + return const Text(''); + }, + ), + ), + leftTitles: AxisTitles( + sideTitles: SideTitles( + showTitles: true, + reservedSize: 50, + getTitlesWidget: (final double value, final TitleMeta meta) => + Text( + '${value.toInt()} €', + style: const TextStyle(fontSize: 12), + ), + ), + ), + ), + lineBarsData: [ + LineChartBarData( + spots: List.generate( + monthlyBalance.length, + (final int index) => FlSpot( + index.toDouble(), + monthlyBalance.values.elementAt(index), + ), + ), + isCurved: true, + barWidth: 3, + color: theme.colorScheme.primary, + ), + ], + ), + ), + ); + } + + /// Erstellt Widgets für die letzten Transaktionen. + /// + /// [recentTransactions] ist eine Liste von Transaktionen, + /// wobei jede Transaktion ein Map mit den Keys 'name' (String) + /// und 'amount' (double) ist. + /// Die Funktion gibt eine Liste von Widgets zurück, + /// die die Transaktionen anzeigen. + List _recentTransactions( + final List> recentTransactions, + ) => recentTransactions + .map( + (final Map tx) => Padding( + padding: const EdgeInsets.symmetric(vertical: 4), + child: ListTile( + contentPadding: EdgeInsets.zero, + title: Text((tx['name'] ?? '') as String), + trailing: Text( + '${((tx['amount'] ?? 0) as double).abs().toStringAsFixed(2)} €', + style: TextStyle( + color: ((tx['amount'] ?? 0) as double) >= 0 + ? Colors.green + : Colors.red, + fontWeight: FontWeight.bold, + ), + ), + ), + ), + ) + .toList(); }