From a2528def2479f0cf2d854fb5306fd0b8595ed74b Mon Sep 17 00:00:00 2001 From: Florian Date: Mon, 31 Aug 2026 15:33:06 +0200 Subject: [PATCH] Added Report Details page --- ac_web/lib/Pages/ReportDetails.dart | 109 +++++++++++++++++++++ ac_web/lib/Widgets/LatestReportColumn.dart | 16 ++- 2 files changed, 122 insertions(+), 3 deletions(-) create mode 100644 ac_web/lib/Pages/ReportDetails.dart diff --git a/ac_web/lib/Pages/ReportDetails.dart b/ac_web/lib/Pages/ReportDetails.dart new file mode 100644 index 0000000..c11b61d --- /dev/null +++ b/ac_web/lib/Pages/ReportDetails.dart @@ -0,0 +1,109 @@ +import 'package:ac_web/Api/Dtos/EReportType.dart'; +import 'package:ac_web/Api/Dtos/ReportDto.dart'; +import 'package:flutter/material.dart'; + +/// Page that shows every detail of a single report, including the full text. +class ReportDetails extends StatelessWidget{ + const ReportDetails({super.key, required this.report}); + + final ReportDto report; + + @override + Widget build(BuildContext context) { + + final DateTime local = report.timestamp.toLocal(); + + return Scaffold( + appBar: AppBar( + title: Text(report.title.isEmpty ? "Report" : report.title), + ), + body: SingleChildScrollView( + padding: EdgeInsetsGeometry.all(16), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + spacing: 12, + children: [ + Row( + spacing: 8, + children: [ + Icon(_iconOf(report.type)), + Expanded( + child: Text( + report.title.isEmpty ? "Untitled Report" : report.title, + style: Theme.of(context).textTheme.headlineSmall, + ), + ), + ], + ), + _buildInfoRow(context, "Type", report.type.displayName), + _buildInfoRow(context, "Author", report.author), + _buildInfoRow(context, "Date", _formatTimestamp(local)), + _buildInfoRow(context, "Id", report.id), + const Divider(), + SelectableText( + report.text.isEmpty ? "This report has no text." : report.text, + style: Theme.of(context).textTheme.bodyMedium, + ), + ], + ), + ), + ); + } + + Widget _buildInfoRow(BuildContext context, String label, String value) { + return Row( + crossAxisAlignment: CrossAxisAlignment.start, + spacing: 8, + children: [ + SizedBox( + width: 80, + child: Text( + label, + style: Theme.of(context).textTheme.labelLarge, + ), + ), + Expanded(child: SelectableText(value)), + ], + ); + } + + /// "15. August 2025, 14:32" + String _formatTimestamp(DateTime timestamp) { + final String hour = timestamp.hour.toString().padLeft(2, '0'); + final String minute = timestamp.minute.toString().padLeft(2, '0'); + + return "${timestamp.day}. ${_monthNames[timestamp.month - 1]} ${timestamp.year}, $hour:$minute"; + } + + static IconData _iconOf(EReportType type) { + switch(type){ + case EReportType.log: + return Icons.receipt_long; + case EReportType.codeReview: + return Icons.code; + case EReportType.projectPlan: + return Icons.assignment; + case EReportType.research: + return Icons.science; + case EReportType.newspaper: + return Icons.newspaper; + case EReportType.unknown: + return Icons.question_mark; + } + } + + static const List _monthNames = [ + "January", + "February", + "March", + "April", + "May", + "June", + "July", + "August", + "September", + "October", + "November", + "December", + ]; +} diff --git a/ac_web/lib/Widgets/LatestReportColumn.dart b/ac_web/lib/Widgets/LatestReportColumn.dart index af19dff..b52065e 100644 --- a/ac_web/lib/Widgets/LatestReportColumn.dart +++ b/ac_web/lib/Widgets/LatestReportColumn.dart @@ -1,6 +1,7 @@ import 'package:ac_web/Api/AcApi.dart'; import 'package:ac_web/Api/Dtos/EReportType.dart'; import 'package:ac_web/Api/Dtos/ReportDto.dart'; +import 'package:ac_web/Pages/ReportDetails.dart'; import 'package:ac_web/Widgets/LatestReportEntry.dart'; import 'package:ac_web/Widgets/LatestReportHeader.dart'; import 'package:flutter/material.dart'; @@ -64,6 +65,8 @@ class _LatestReportColumnState extends State{ lastDay = day; } + final ReportDto report = reports[i]; + IconData icon; switch(reports[i].type){ @@ -85,9 +88,7 @@ class _LatestReportColumnState extends State{ widgets.add(LatestReportEntry( text: reports[i].title, icon: icon, - onTap: () => {widgets.add( - LatestReportHeader(text: "WOOOD") - )}, + onTap: () => _openReport(report), )); } @@ -97,6 +98,15 @@ class _LatestReportColumnState extends State{ ); } + /// Opens a new page that shows all details of the given report. + void _openReport(ReportDto report) { + Navigator.of(context).push( + MaterialPageRoute( + builder: (context) => ReportDetails(report: report), + ), + ); + } + /// Strips the time part, so that two timestamps of the same day are equal. DateTime _dayOf(DateTime timestamp) { final DateTime local = timestamp.toLocal();