import 'dart:convert';
import '../data/demo_report_store.dart';
import '../data/report_photo_store.dart';
class ReportDocument {
const ReportDocument({
required this.report,
required this.companyName,
required this.companyAddress,
required this.companyContact,
required this.reportFooter,
required this.participantNames,
this.photos = const [],
});
final DemoReport report;
final String companyName;
final String companyAddress;
final String companyContact;
final String reportFooter;
final List<String> participantNames;
final List<ReportPhoto> photos;
}
abstract interface class ReportExporter {
String get format;
String get mimeType;
String fileName(ReportDocument document);
Future<List<int>> export(ReportDocument document);
}
class CsvReportExporter implements ReportExporter {
const CsvReportExporter();
@override
String get format => 'CSV';
@override
String get mimeType => 'text/csv; charset=utf-8';
@override
String fileName(ReportDocument document) {
final date = document.report.date.toIso8601String().split('T').first;
final site = document.report.site.replaceAll(
RegExp(r'[^a-zA-Z0-9äöüÄÖÜß]+'),
'_',
);
return 'MACHWEIS_${date}_$site.csv';
}
@override
Future<List<int>> export(ReportDocument document) async =>
utf8.encode(asText(document));
String asText(ReportDocument document) {
final report = document.report;
final rows = <List<String>>[
['MACHWEIS Leistungsnachweis'],
['Firma', document.companyName],
['Firmenanschrift', document.companyAddress],
['Kontakt', document.companyContact],
['Kunde', report.customer],
['Baustelle / Auftrag', report.site],
['Datum', report.date.toIso8601String().split('T').first],
[
'Arbeitszeit',
'${_time(report.start.hour, report.start.minute)} - ${_time(report.end.hour, report.end.minute)}',
],
['Pause', '${report.breakMinutes} Minuten'],
['Nettoarbeitszeit', _duration(report.netMinutes)],
['Mitarbeiter', document.participantNames.join(', ')],
[],
['Leistungsposition', 'Beschreibung'],
for (var index = 0; index < report.activityItems.length; index++)
['${index + 1}', report.activityItems[index]],
[],
['Materialposition', 'Material', 'Menge', 'Einheit'],
for (var index = 0; index < report.materialItems.length; index++)
[
'${index + 1}',
report.materialItems[index].name,
report.materialItems[index].quantity,
report.materialItems[index].unit,
],
if (report.additionalOrder.isNotEmpty) ...[
[],
['Zusatzauftrag', report.additionalOrder],
[
'Zusatzauftrag bestätigt',
report.additionalOrderApproved ? 'Ja' : 'Nein',
],
],
[],
['Status', report.isFinalized ? 'Abgeschlossen' : 'Entwurf'],
['Unterschrieben am', report.finalizedAt?.toIso8601String() ?? ''],
['Berichtshinweis', document.reportFooter],
];
return rows.map((row) => row.map(_escape).join(';')).join('\r\n');
}
String _escape(String value) => '"${value.replaceAll('"', '""')}"';
String _time(int hour, int minute) =>
'${hour.toString().padLeft(2, '0')}:${minute.toString().padLeft(2, '0')}';
String _duration(int minutes) =>
'${minutes ~/ 60}:${(minutes % 60).toString().padLeft(2, '0')} Stunden';
}
abstract interface class PdfReportRenderer implements ReportExporter {
@override
String get format => 'PDF';
@override
String get mimeType => 'application/pdf';
}
