diff --git a/lib/screens/report_screen.dart b/lib/screens/report_screen.dart index 1c56861..b24c37e 100644 --- a/lib/screens/report_screen.dart +++ b/lib/screens/report_screen.dart @@ -1,7 +1,6 @@ import 'dart:developer'; import 'package:fl_chart/fl_chart.dart'; -import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:flutter_platform_widgets/flutter_platform_widgets.dart'; import 'package:flutter_slidable/flutter_slidable.dart'; @@ -16,14 +15,12 @@ DateTime unixSecondsToDateTime(int ts) => DateTime.fromMillisecondsSinceEpoch(ts * 1000, isUtc: true).toLocal(); extension TimeEntryFormatting on TimeEntry { - /// Konvertiert den startTime (Unix Timestamp) in ein lokales DateTime Objekt. DateTime get startDateTime => DateTime.fromMillisecondsSinceEpoch( startTime.toInt() * 1000, isUtc: true, ).toLocal(); - /// Konvertiert den optionalen endTime (Unix Timestamp) in ein lokales DateTime Objekt. DateTime? get endDateTime => endTime == null ? null @@ -32,7 +29,6 @@ extension TimeEntryFormatting on TimeEntry { isUtc: true, ).toLocal(); - /// Formatiert die Dauer (durationSecs) als HH:MM:SS String. String get durationFormatted { final durationInSeconds = durationSecs?.toInt(); if (durationInSeconds == null || durationInSeconds < 0) return '--:--:--'; @@ -47,7 +43,6 @@ extension TimeEntryFormatting on TimeEntry { } extension ReportDataFormatting on ReportData { - /// Formatiert die Gesamtdauer als HH:MM:SS String. String get totalDurationFormatted { final durationInSeconds = totalDurationSecs.toInt(); if (durationInSeconds < 0) return '--:--:--'; @@ -99,8 +94,9 @@ class _ReportScreenState extends State { final Map> dailyTagDurations = {}; for (final entry in entries) { - if (entry.durationSecs == null || entry.durationSecs!.toInt() <= 0) + if (entry.durationSecs == null || entry.durationSecs!.toInt() <= 0) { continue; + } final entryDay = DateTime( entry.startDateTime.year, @@ -393,14 +389,24 @@ class _ReportScreenState extends State { children: [ _buildFilterControls(tagOptions), Expanded( - child: - _isLoadingReport - ? Center(child: PlatformCircularProgressIndicator()) - : _reportData == null - ? const Center( - child: Text('Keine Reportdaten gefunden oder Fehler.'), - ) - : _buildReportView(), + child: RefreshIndicator.adaptive( + onRefresh: _generateReport, + child: + _isLoadingReport + ? Center(child: PlatformCircularProgressIndicator()) + : _reportData == null + ? ListView( + children: [ + SizedBox( + height: MediaQuery.of(context).size.height * 0.5, + child: Text( + 'Keine Reportdaten gefunden oder Fehler.', + ), + ), + ], + ) + : _buildReportView(), + ), ), ], ), @@ -487,8 +493,6 @@ class _ReportScreenState extends State { ), ), ), - // SizedBox(height: 250, child: _buildPieChart(_reportData!)), - // const Divider(), SizedBox( height: 250, child: _buildBarChart(_reportData!, startDate, endDate), @@ -512,103 +516,6 @@ class _ReportScreenState extends State { ); } - Widget _buildPieChart(ReportData data) { - Map durationPerTag = {}; - for (var entry in data.entries) { - final tagName = entry.tagName ?? 'Ohne Tag'; - final duration = (entry.durationSecs?.toInt() ?? 0).toDouble(); - durationPerTag[tagName] = (durationPerTag[tagName] ?? 0) + duration; - } - - if (durationPerTag.isEmpty) { - return const Center(child: Text("Keine Daten für Chart")); - } - - List colors = Colors.primaries.take(durationPerTag.length).toList(); - if (durationPerTag.length > Colors.primaries.length) { - colors.addAll( - Colors.accents.take(durationPerTag.length - Colors.primaries.length), - ); - } - - int colorIndex = 0; - List sections = - durationPerTag.entries.map((entry) { - final isTouched = false; - final fontSize = isTouched ? 18.0 : 14.0; - final radius = isTouched ? 60.0 : 50.0; - final color = colors[colorIndex % colors.length]; - colorIndex++; - - final hours = (entry.value / 3600).toStringAsFixed(1); - - return PieChartSectionData( - color: color, - value: entry.value, - title: '${entry.key}\n${hours}h', - radius: radius, - titleStyle: TextStyle( - fontSize: fontSize, - fontWeight: FontWeight.bold, - color: Colors.white, - shadows: [ - Shadow(color: Colors.black.withOpacity(0.7), blurRadius: 2), - ], - ), - titlePositionPercentageOffset: 0.6, - ); - }).toList(); - - return Padding( - padding: const EdgeInsets.all(8.0), - child: PieChart( - PieChartData( - sections: sections, - centerSpaceRadius: 40, - sectionsSpace: 2, - ), - duration: const Duration(milliseconds: 150), - curve: Curves.linear, - ), - ); - } - - // Widget _buildDataTable(List entries) { - // final DateFormat timeFormatter = DateFormat('HH:mm:ss'); - // final DateFormat dateFormatter = DateFormat('dd.MM.yy'); - - // return DataTable( - // columnSpacing: 10, - // columns: [ - // DataColumn(label: PlatformText('Tag')), - // DataColumn(label: PlatformText('Start')), - // DataColumn(label: PlatformText('Ende')), - // DataColumn(label: PlatformText('Dauer'), numeric: true), - // ], - // rows: - // entries.map((entry) { - // return DataRow( - // cells: [ - // DataCell(PlatformText(entry.tagName ?? '-')), - // DataCell( - // PlatformText( - // '${dateFormatter.format(unixSecondsToDateTime(entry.startTime))}\n${timeFormatter.format(unixSecondsToDateTime(entry.startTime))}', - // ), - // ), - // DataCell( - // entry.endTime != null - // ? PlatformText( - // '${dateFormatter.format(unixSecondsToDateTime(entry.endTime!))}\n${timeFormatter.format(unixSecondsToDateTime(entry.endTime!))}', - // ) - // : PlatformText('-'), - // ), - // DataCell(Text(entry.durationFormatted)), - // ], - // ); - // }).toList(), - // ); - // } - void _confirmAndDeleteEntry(TimeEntry entry, BuildContext context) { showPlatformDialog( context: context, @@ -855,10 +762,7 @@ class _ReportScreenState extends State { actions: [ PlatformDialogAction( child: PlatformText('OK'), - onPressed: - () => Navigator.pop( - dialogContext, - ), // Pop using dialog's context + onPressed: () => Navigator.pop(dialogContext), ), ], ),