Resolve all lints and deprecation warnings

This commit is contained in:
2026-01-09 10:04:51 -06:00
parent 512577b092
commit a799e9cf59
56 changed files with 2819 additions and 3159 deletions

View File

@@ -1,105 +1,109 @@
import 'dart:typed_data';
import 'package:flutter/services.dart';
import 'package:pdf/pdf.dart';
import 'package:pdf/widgets.dart' as pw;
import 'package:printing/printing.dart';
import 'package:intl/intl.dart';
import '../models/user_profile.dart';
import '../models/cycle_entry.dart';
import 'package:intl/intl.dart';
class PdfService {
static Future<void> generateCycleReport(UserProfile? user, List<CycleEntry> entries) async {
static Future<void> generateCycleReport(
UserProfile user, List<CycleEntry> entries) async {
final pdf = pw.Document();
final font = await PdfGoogleFonts.outfitRegular();
final boldFont = await PdfGoogleFonts.outfitBold();
final logo = pw.MemoryImage(
(await rootBundle.load('assets/images/logo.png')).buffer.asUint8List(),
);
// Group entries by month
final entriesByMonth = <String, List<CycleEntry>>{};
final Map<String, List<CycleEntry>> groupedEntries = {};
for (var entry in entries) {
final month = DateFormat('MMMM yyyy').format(entry.date);
if (!entriesByMonth.containsKey(month)) {
entriesByMonth[month] = [];
if (!groupedEntries.containsKey(month)) {
groupedEntries[month] = [];
}
entriesByMonth[month]!.add(entry);
groupedEntries[month]!.add(entry);
}
// Sort months chronologically (most recent first)
final sortedMonths = groupedEntries.keys.toList()
..sort((a, b) {
final dateA = DateFormat('MMMM yyyy').parse(a);
final dateB = DateFormat('MMMM yyyy').parse(b);
return dateB.compareTo(dateA);
});
pdf.addPage(
pw.MultiPage(
pageFormat: PdfPageFormat.a4,
theme: pw.ThemeData.withFont(
base: font,
bold: boldFont,
),
margin: const pw.EdgeInsets.all(32),
build: (pw.Context context) {
return [
pw.Header(
level: 0,
child: pw.Row(
mainAxisAlignment: pw.MainAxisAlignment.spaceBetween,
children: [
pw.Text('Cycle Report', style: pw.TextStyle(fontSize: 24, fontWeight: pw.FontWeight.bold)),
pw.Text(DateFormat.yMMMd().format(DateTime.now()), style: const pw.TextStyle(color: PdfColors.grey)),
],
),
),
if (user != null)
pw.Padding(
padding: const pw.EdgeInsets.only(bottom: 20),
child: pw.Column(
pw.Row(
mainAxisAlignment: pw.MainAxisAlignment.spaceBetween,
children: [
pw.Column(
crossAxisAlignment: pw.CrossAxisAlignment.start,
children: [
pw.Text('Name: ${user.name}'),
pw.Text('Average Cycle Length: ${user.averageCycleLength} days'),
pw.Text('Average Period Length: ${user.averagePeriodLength} days'),
pw.Text('Cycle History Report',
style: pw.TextStyle(
fontSize: 24,
fontWeight: pw.FontWeight.bold,
color: PdfColors.blueGrey900)),
pw.Text('Generated for ${user.name}',
style: const pw.TextStyle(
fontSize: 14, color: PdfColors.blueGrey600)),
pw.Text(
'Date Range: ${DateFormat('MMM yyyy').format(entries.last.date)} - ${DateFormat('MMM yyyy').format(entries.first.date)}',
style: const pw.TextStyle(
fontSize: 12, color: PdfColors.blueGrey400)),
],
),
),
...entriesByMonth.entries.map((entry) {
final month = entry.key;
final monthEntries = entry.value;
// Sort by date
monthEntries.sort((a, b) => a.date.compareTo(b.date));
return pw.Column(
pw.SizedBox(height: 50, width: 50, child: pw.Image(logo)),
],
),
pw.SizedBox(height: 30),
for (var month in sortedMonths) ...[
pw.Column(
crossAxisAlignment: pw.CrossAxisAlignment.start,
children: [
pw.SizedBox(height: 10),
pw.Text(month, style: pw.TextStyle(fontSize: 18, fontWeight: pw.FontWeight.bold, color: PdfColors.blueGrey800)),
pw.Text(month,
style: pw.TextStyle(
fontSize: 18,
fontWeight: pw.FontWeight.bold,
color: PdfColors.blueGrey800)),
pw.SizedBox(height: 5),
pw.Table.fromTextArray(
pw.TableHelper.fromTextArray(
context: context,
headerStyle: pw.TextStyle(fontWeight: pw.FontWeight.bold),
headers: ['Date', 'Phase', 'Details', 'Notes'],
data: monthEntries.map((e) {
final details = <String>[];
if (e.isPeriodDay) details.add('Period');
if (e.mood != null) details.add('Mood: ${e.mood!.label}');
if (e.symptomCount > 0) details.add('${e.symptomCount} symptoms');
data: groupedEntries[month]!.map((e) {
return [
DateFormat('d, E').format(e.date),
'${e.isPeriodDay ? "Menstrual" : "-"}', // Simplified for report
details.join(', '),
e.notes ?? '',
DateFormat('MMM d').format(e.date),
e.isPeriodDay
? 'Period'
: (e.flowIntensity == FlowIntensity.spotting
? 'Spotting'
: 'Other'),
e.flowIntensity != null
? 'Flow: ${e.flowIntensity.toString().split('.').last}'
: '-',
e.notes ?? '-',
];
}).toList(),
columnWidths: {
0: const pw.FlexColumnWidth(1),
1: const pw.FlexColumnWidth(1),
2: const pw.FlexColumnWidth(2),
3: const pw.FlexColumnWidth(2),
},
),
pw.SizedBox(height: 15),
pw.SizedBox(height: 20),
],
);
}),
),
],
];
},
),
);
await Printing.sharePdf(bytes: await pdf.save(), filename: 'cycle_report.pdf');
await Printing.layoutPdf(
onLayout: (PdfPageFormat format) async => pdf.save(),
);
}
}