Added Report Details page
This commit is contained in:
@@ -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<String> _monthNames = <String>[
|
||||||
|
"January",
|
||||||
|
"February",
|
||||||
|
"March",
|
||||||
|
"April",
|
||||||
|
"May",
|
||||||
|
"June",
|
||||||
|
"July",
|
||||||
|
"August",
|
||||||
|
"September",
|
||||||
|
"October",
|
||||||
|
"November",
|
||||||
|
"December",
|
||||||
|
];
|
||||||
|
}
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
import 'package:ac_web/Api/AcApi.dart';
|
import 'package:ac_web/Api/AcApi.dart';
|
||||||
import 'package:ac_web/Api/Dtos/EReportType.dart';
|
import 'package:ac_web/Api/Dtos/EReportType.dart';
|
||||||
import 'package:ac_web/Api/Dtos/ReportDto.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/LatestReportEntry.dart';
|
||||||
import 'package:ac_web/Widgets/LatestReportHeader.dart';
|
import 'package:ac_web/Widgets/LatestReportHeader.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
@@ -64,6 +65,8 @@ class _LatestReportColumnState extends State<LatestReportColumn>{
|
|||||||
lastDay = day;
|
lastDay = day;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
final ReportDto report = reports[i];
|
||||||
|
|
||||||
IconData icon;
|
IconData icon;
|
||||||
|
|
||||||
switch(reports[i].type){
|
switch(reports[i].type){
|
||||||
@@ -85,9 +88,7 @@ class _LatestReportColumnState extends State<LatestReportColumn>{
|
|||||||
widgets.add(LatestReportEntry(
|
widgets.add(LatestReportEntry(
|
||||||
text: reports[i].title,
|
text: reports[i].title,
|
||||||
icon: icon,
|
icon: icon,
|
||||||
onTap: () => {widgets.add(
|
onTap: () => _openReport(report),
|
||||||
LatestReportHeader(text: "WOOOD")
|
|
||||||
)},
|
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -97,6 +98,15 @@ class _LatestReportColumnState extends State<LatestReportColumn>{
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Opens a new page that shows all details of the given report.
|
||||||
|
void _openReport(ReportDto report) {
|
||||||
|
Navigator.of(context).push(
|
||||||
|
MaterialPageRoute<void>(
|
||||||
|
builder: (context) => ReportDetails(report: report),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
/// Strips the time part, so that two timestamps of the same day are equal.
|
/// Strips the time part, so that two timestamps of the same day are equal.
|
||||||
DateTime _dayOf(DateTime timestamp) {
|
DateTime _dayOf(DateTime timestamp) {
|
||||||
final DateTime local = timestamp.toLocal();
|
final DateTime local = timestamp.toLocal();
|
||||||
|
|||||||
Reference in New Issue
Block a user