fix(pdf): make footer and all content stay compact and strictly within half-sheet area

This commit is contained in:
=
2026-09-21 22:37:39 -04:00
parent 9263e3486f
commit dc39eab3ae
5 changed files with 91 additions and 60 deletions
@@ -74,9 +74,12 @@ class InsuranceAuthPdfService {
crossAxisAlignment: pw.CrossAxisAlignment.stretch, crossAxisAlignment: pw.CrossAxisAlignment.stretch,
children: [ children: [
// Mitad superior de la hoja (máximo 5.5 pulgadas / 396 pt) // Mitad superior de la hoja (máximo 5.5 pulgadas / 396 pt)
pw.Container( pw.ConstrainedBox(
height: 5.5 * PdfPageFormat.inch - 36, constraints: const pw.BoxConstraints(
maxHeight: 5.5 * PdfPageFormat.inch - 36,
),
child: pw.Column( child: pw.Column(
mainAxisSize: pw.MainAxisSize.min,
crossAxisAlignment: pw.CrossAxisAlignment.stretch, crossAxisAlignment: pw.CrossAxisAlignment.stretch,
children: [ children: [
// 1. Cabecera con Nombre del Doctor y Badge Sutil de Hidalyx Med // 1. Cabecera con Nombre del Doctor y Badge Sutil de Hidalyx Med
@@ -207,10 +210,10 @@ class InsuranceAuthPdfService {
pw.SizedBox(height: 8), pw.SizedBox(height: 8),
// 3. Contenido Formal idéntico a AlfaMedical // 3. Contenido Formal idéntico a AlfaMedical
pw.Expanded( pw.Column(
child: pw.Column( crossAxisAlignment: pw.CrossAxisAlignment.stretch,
crossAxisAlignment: pw.CrossAxisAlignment.stretch, mainAxisSize: pw.MainAxisSize.min,
children: [ children: [
// Señores ARS // Señores ARS
pw.RichText( pw.RichText(
text: pw.TextSpan( text: pw.TextSpan(
@@ -311,8 +314,14 @@ class InsuranceAuthPdfService {
], ],
], ],
), ),
pw.SizedBox(height: 10),
// Línea divisoria decorativa previa al pie
pw.Container(
height: 0.5,
color: PdfColor.fromHex('CBD5E1'),
), ),
pw.SizedBox(height: 6), pw.SizedBox(height: 5),
// 4. Pie de página con Contacto del Consultorio // 4. Pie de página con Contacto del Consultorio
if (generalContact.isNotEmpty) ...[ if (generalContact.isNotEmpty) ...[
@@ -71,9 +71,12 @@ class PrescriptionPdfService {
crossAxisAlignment: pw.CrossAxisAlignment.stretch, crossAxisAlignment: pw.CrossAxisAlignment.stretch,
children: [ children: [
// Mitad superior de la hoja (máximo 5.5 pulgadas / 396 pt) // Mitad superior de la hoja (máximo 5.5 pulgadas / 396 pt)
pw.Container( pw.ConstrainedBox(
height: 5.5 * PdfPageFormat.inch - 36, constraints: const pw.BoxConstraints(
maxHeight: 5.5 * PdfPageFormat.inch - 36,
),
child: pw.Column( child: pw.Column(
mainAxisSize: pw.MainAxisSize.min,
crossAxisAlignment: pw.CrossAxisAlignment.stretch, crossAxisAlignment: pw.CrossAxisAlignment.stretch,
children: [ children: [
// 1. Cabecera con Nombre del Doctor y Badge Superior de Hidalyx Med // 1. Cabecera con Nombre del Doctor y Badge Superior de Hidalyx Med
@@ -219,28 +222,33 @@ class PrescriptionPdfService {
pw.SizedBox(height: 8), pw.SizedBox(height: 8),
// 3. Contenido de la Receta / Prescripción Médica // 3. Contenido de la Receta / Prescripción Médica
pw.Expanded( pw.Container(
child: pw.Container( padding: const pw.EdgeInsets.symmetric(vertical: 6),
padding: const pw.EdgeInsets.symmetric(vertical: 4), child: pw.Text(
child: pw.Text( prescriptionText.trim().isNotEmpty
prescriptionText.trim().isNotEmpty ? prescriptionText.trim()
? prescriptionText.trim() : 'Sin prescripciones anotadas.',
: 'Sin prescripciones anotadas.', style: pw.TextStyle(
style: pw.TextStyle( font: regular,
font: regular, fontSize: 10,
fontSize: 10, lineSpacing: 3,
lineSpacing: 3, color: PdfColor.fromHex('1E293B'),
color: PdfColor.fromHex('1E293B'),
),
), ),
), ),
), ),
pw.SizedBox(height: 6), pw.SizedBox(height: 10),
// Línea sutil previa al pie de página
pw.Container(
height: 0.5,
color: PdfColor.fromHex('CBD5E1'),
),
pw.SizedBox(height: 5),
// 4. Pie de página con Contacto del Consultorio // 4. Pie de página con Contacto del Consultorio
if (generalContact.isNotEmpty) ...[ if (generalContact.isNotEmpty) ...[
pw.Container( pw.Container(
padding: const pw.EdgeInsets.only(top: 4), padding: const pw.EdgeInsets.only(top: 2),
child: pw.Text( child: pw.Text(
generalContact.toUpperCase(), generalContact.toUpperCase(),
textAlign: pw.TextAlign.center, textAlign: pw.TextAlign.center,
@@ -252,10 +260,9 @@ class PrescriptionPdfService {
), ),
), ),
), ),
pw.SizedBox(height: 3),
], ],
pw.SizedBox(height: 3),
// Confirmación institucional // Confirmación institucional
pw.Center( pw.Center(
child: pw.Text( child: pw.Text(
@@ -69,9 +69,12 @@ class DepartmentReferralPdfService {
crossAxisAlignment: pw.CrossAxisAlignment.stretch, crossAxisAlignment: pw.CrossAxisAlignment.stretch,
children: [ children: [
// Mitad superior de la hoja (máximo 5.5 pulgadas / 396 pt) // Mitad superior de la hoja (máximo 5.5 pulgadas / 396 pt)
pw.Container( pw.ConstrainedBox(
height: 5.5 * PdfPageFormat.inch - 36, constraints: const pw.BoxConstraints(
maxHeight: 5.5 * PdfPageFormat.inch - 36,
),
child: pw.Column( child: pw.Column(
mainAxisSize: pw.MainAxisSize.min,
crossAxisAlignment: pw.CrossAxisAlignment.stretch, crossAxisAlignment: pw.CrossAxisAlignment.stretch,
children: [ children: [
// 1. Cabecera con Nombre del Doctor y Badge Sutil de Hidalyx Med // 1. Cabecera con Nombre del Doctor y Badge Sutil de Hidalyx Med
@@ -168,23 +171,28 @@ class DepartmentReferralPdfService {
pw.SizedBox(height: 8), pw.SizedBox(height: 8),
// 2. Contenido del Referimiento (Idéntico a AlfaMedical) // 2. Contenido del Referimiento (Idéntico a AlfaMedical)
pw.Expanded( pw.Container(
child: pw.Container( padding: const pw.EdgeInsets.symmetric(vertical: 6),
padding: const pw.EdgeInsets.symmetric(vertical: 4), child: pw.Text(
child: pw.Text( referralText.trim().isNotEmpty
referralText.trim().isNotEmpty ? referralText.trim()
? referralText.trim() : 'Sin detalles de referimiento.',
: 'Sin detalles de referimiento.', style: pw.TextStyle(
style: pw.TextStyle( font: regular,
font: regular, fontSize: 10.5,
fontSize: 10.5, lineSpacing: 3.5,
lineSpacing: 3.5, color: PdfColor.fromHex('1E293B'),
color: PdfColor.fromHex('1E293B'),
),
), ),
), ),
), ),
pw.SizedBox(height: 6), pw.SizedBox(height: 10),
// Línea divisoria decorativa previa al pie
pw.Container(
height: 0.5,
color: PdfColor.fromHex('CBD5E1'),
),
pw.SizedBox(height: 5),
// 3. Pie de página con Contacto del Consultorio // 3. Pie de página con Contacto del Consultorio
if (generalContact.isNotEmpty) ...[ if (generalContact.isNotEmpty) ...[
@@ -69,9 +69,12 @@ class DoctorReferralPdfService {
crossAxisAlignment: pw.CrossAxisAlignment.stretch, crossAxisAlignment: pw.CrossAxisAlignment.stretch,
children: [ children: [
// Mitad superior de la hoja (máximo 5.5 pulgadas / 396 pt) // Mitad superior de la hoja (máximo 5.5 pulgadas / 396 pt)
pw.Container( pw.ConstrainedBox(
height: 5.5 * PdfPageFormat.inch - 36, constraints: const pw.BoxConstraints(
maxHeight: 5.5 * PdfPageFormat.inch - 36,
),
child: pw.Column( child: pw.Column(
mainAxisSize: pw.MainAxisSize.min,
crossAxisAlignment: pw.CrossAxisAlignment.stretch, crossAxisAlignment: pw.CrossAxisAlignment.stretch,
children: [ children: [
// 1. Cabecera con Nombre del Doctor y Badge Sutil de Hidalyx Med // 1. Cabecera con Nombre del Doctor y Badge Sutil de Hidalyx Med
@@ -168,23 +171,28 @@ class DoctorReferralPdfService {
pw.SizedBox(height: 8), pw.SizedBox(height: 8),
// 2. Contenido del Referimiento (Idéntico a AlfaMedical con fontSize 13-14) // 2. Contenido del Referimiento (Idéntico a AlfaMedical con fontSize 13-14)
pw.Expanded( pw.Container(
child: pw.Container( padding: const pw.EdgeInsets.symmetric(vertical: 6),
padding: const pw.EdgeInsets.symmetric(vertical: 4), child: pw.Text(
child: pw.Text( referralText.trim().isNotEmpty
referralText.trim().isNotEmpty ? referralText.trim()
? referralText.trim() : 'Sin detalles de referimiento.',
: 'Sin detalles de referimiento.', style: pw.TextStyle(
style: pw.TextStyle( font: regular,
font: regular, fontSize: 10.5,
fontSize: 10.5, lineSpacing: 3.5,
lineSpacing: 3.5, color: PdfColor.fromHex('1E293B'),
color: PdfColor.fromHex('1E293B'),
),
), ),
), ),
), ),
pw.SizedBox(height: 6), pw.SizedBox(height: 10),
// Línea divisoria decorativa previa al pie
pw.Container(
height: 0.5,
color: PdfColor.fromHex('CBD5E1'),
),
pw.SizedBox(height: 5),
// 3. Pie de página con Contacto del Consultorio // 3. Pie de página con Contacto del Consultorio
if (generalContact.isNotEmpty) ...[ if (generalContact.isNotEmpty) ...[
+1 -2
View File
@@ -104,7 +104,7 @@ void main() {
}); });
group('PrescriptionPdfService Tests', () { group('PrescriptionPdfService Tests', () {
test('builds prescription pdf bytes with correct page format', () async { test('builds prescription pdf bytes with correct page format and layout', () async {
final bytes = await PrescriptionPdfService.buildPrescriptionPdf( final bytes = await PrescriptionPdfService.buildPrescriptionPdf(
doctorName: 'Dr. Luis A. Castro Sosa', doctorName: 'Dr. Luis A. Castro Sosa',
specialty: 'Cirujano Urólogo', specialty: 'Cirujano Urólogo',
@@ -115,7 +115,6 @@ void main() {
); );
expect(bytes, isNotEmpty); expect(bytes, isNotEmpty);
// Valid PDF magic header %PDF
expect(bytes.sublist(0, 4), equals([0x25, 0x50, 0x44, 0x46])); expect(bytes.sublist(0, 4), equals([0x25, 0x50, 0x44, 0x46]));
}); });
}); });