Proper signatories

This commit is contained in:
2026-02-21 23:31:17 +08:00
parent d778654837
commit 74f9511ee3
2 changed files with 350 additions and 185 deletions
+34 -185
View File
@@ -13,11 +13,8 @@ import 'dart:async';
import 'dart:convert';
import 'package:file_picker/file_picker.dart';
import 'package:flutter_quill/flutter_quill.dart' as quill;
import 'dart:typed_data';
import 'package:flutter/services.dart' show rootBundle;
import 'package:pdf/widgets.dart' as pw;
import 'package:pdf/pdf.dart' as pdf;
import 'package:printing/printing.dart';
import '../../providers/services_provider.dart';
import 'task_pdf.dart';
import '../../providers/supabase_provider.dart';
import 'package:flutter_typeahead/flutter_typeahead.dart';
import '../../providers/profile_provider.dart';
@@ -361,7 +358,37 @@ class _TaskDetailScreenState extends ConsumerState<TaskDetailScreen>
tooltip: 'Preview/print task',
onPressed: () async {
try {
await _showPdfPreview(task, ticket, officeName);
final logsAsync = ref.read(
taskActivityLogsProvider(task.id),
);
final logs =
logsAsync.valueOrNull ?? <TaskActivityLog>[];
final assignmentList = assignments;
final profilesList =
profilesAsync.valueOrNull ?? <Profile>[];
final servicesAsync = ref.read(servicesProvider);
final servicesById = {
for (final s in servicesAsync.valueOrNull ?? [])
s.id: s,
};
final serviceName = officeId == null
? ''
: (officeById[officeId]?.serviceId == null
? ''
: (servicesById[officeById[officeId]!
.serviceId]
?.name ??
''));
await showTaskPdfPreview(
context,
task,
ticket,
officeName,
serviceName,
logs,
assignmentList,
profilesList,
);
} catch (_) {}
},
icon: const Icon(Icons.print),
@@ -2755,185 +2782,7 @@ class _TaskDetailScreenState extends ConsumerState<TaskDetailScreen>
);
}
Future<Uint8List> _buildTaskPdfBytes(
Task task,
Ticket? ticket,
String officeName,
pdf.PdfPageFormat format,
) async {
final logoData = await rootBundle.load('crmc_logo.png');
final logoImage = pw.MemoryImage(logoData.buffer.asUint8List());
final doc = pw.Document();
final created = AppTime.formatDate(task.createdAt);
doc.addPage(
pw.Page(
pageFormat: format,
margin: pw.EdgeInsets.all(28),
build: (pw.Context ctx) {
return pw.Column(
crossAxisAlignment: pw.CrossAxisAlignment.start,
children: [
pw.Row(
crossAxisAlignment: pw.CrossAxisAlignment.start,
children: [
pw.Container(
width: 64,
height: 64,
child: pw.Image(logoImage),
),
pw.SizedBox(width: 12),
pw.Expanded(
child: pw.Column(
crossAxisAlignment: pw.CrossAxisAlignment.center,
children: [
pw.Text(
'Republic of the Philippines',
textAlign: pw.TextAlign.center,
),
pw.Text(
'Department of Health',
textAlign: pw.TextAlign.center,
),
pw.Text(
'Regional and Medical Center',
textAlign: pw.TextAlign.center,
),
pw.SizedBox(height: 6),
pw.Text(
'Cotabato Regional and Medical Center',
textAlign: pw.TextAlign.center,
style: pw.TextStyle(fontWeight: pw.FontWeight.bold),
),
pw.Text(
'Integrated Hospital Operations and Management Program',
textAlign: pw.TextAlign.center,
),
pw.Text('(IHOMP)', textAlign: pw.TextAlign.center),
],
),
),
],
),
pw.SizedBox(height: 12),
pw.Center(
child: pw.Text(
'IT Job / Maintenance Request Form',
style: pw.TextStyle(
fontSize: 16,
fontWeight: pw.FontWeight.bold,
),
),
),
pw.SizedBox(height: 12),
pw.Row(
children: [
pw.Text('Task Number: ${task.taskNumber ?? task.id}'),
pw.Spacer(),
pw.Text('Filed At: $created'),
],
),
pw.SizedBox(height: 8),
pw.Row(
children: [
pw.Text('Service: ${task.title}'),
pw.SizedBox(width: 12),
pw.Text('Office: $officeName'),
],
),
pw.SizedBox(height: 8),
pw.Row(
children: [
pw.Text('Type: ${task.requestType ?? ''}'),
pw.SizedBox(width: 12),
pw.Text('Category: ${task.requestCategory ?? ''}'),
],
),
pw.SizedBox(height: 12),
pw.Text('Description:'),
pw.SizedBox(height: 6),
pw.Container(
height: 80,
decoration: pw.BoxDecoration(
border: pw.Border(
bottom: pw.BorderSide(
width: 0.5,
color: pdf.PdfColors.grey,
),
),
),
),
pw.SizedBox(height: 12),
pw.Row(
children: [
pw.Text('Requested By: ${task.requestedBy ?? ''}'),
pw.Spacer(),
pw.Text('Noted by Supervisor/Senior'),
],
),
pw.SizedBox(height: 12),
pw.Text('Action Taken:'),
pw.SizedBox(height: 6),
pw.Container(
height: 80,
decoration: pw.BoxDecoration(
border: pw.Border(
bottom: pw.BorderSide(
width: 0.5,
color: pdf.PdfColors.grey,
),
),
),
),
pw.SizedBox(height: 12),
pw.Row(
children: [
pw.Text('Performed By:'),
pw.Spacer(),
pw.Text('Received By: ___________________________'),
],
),
],
);
},
),
);
return doc.save();
}
Future<void> _showPdfPreview(
Task task,
Ticket? ticket,
String officeName,
) async {
await showDialog<void>(
context: context,
builder: (ctx) => AlertDialog(
contentPadding: const EdgeInsets.all(8),
content: SizedBox(
width: 700,
height: 900,
child: PdfPreview(
build: (format) => _buildTaskPdfBytes(
task,
ticket,
officeName,
format as pdf.PdfPageFormat,
),
allowPrinting: true,
allowSharing: true,
),
),
actions: [
TextButton(
onPressed: () => Navigator.of(ctx).pop(),
child: const Text('Close'),
),
],
),
);
}
// PDF preview/building moved to `task_pdf.dart`.
}
class _MetaBadge extends StatelessWidget {