Aidra Driver 1.3.5+68
Aidra Driver - Your path to green energy
Loading...
Searching...
No Matches
manifest_pdf.dart
Go to the documentation of this file.
1import 'dart:convert';
2import 'dart:developer';
3import 'dart:io';
4
5import 'package:flutter/services.dart';
6import 'package:open_file/open_file.dart';
7import 'package:path_provider/path_provider.dart';
8import 'package:pdf/pdf.dart';
9import 'package:pdf/widgets.dart' as pw;
10
11import '../../common/models/manifest_document.dart';
12import '../../constants/assets.dart';
13import '../../services/user_info_service.dart';
14
16 ManifestDocument manifest,
17) async {
18 final pdf = pw.Document();
19
20 pw.MemoryImage? signatureImage;
21 try {
22 final String? signatureBase64 =
24 if (signatureBase64 != null && signatureBase64.isNotEmpty) {
25 final Uint8List signatureData = base64Decode(signatureBase64);
26 signatureImage = pw.MemoryImage(signatureData);
27 }
28 } catch (e) {
29 log('Error loading signature: $e');
30 }
31
32 // Load the logo image
33 final ByteData logoBytes = await rootBundle.load(Assets.tajmielogo);
34 final Uint8List logoData = logoBytes.buffer.asUint8List();
35 final pw.MemoryImage logoImage = pw.MemoryImage(logoData);
36
37 // Define colors
38 final PdfColor headerBlue = PdfColor.fromInt(0xFFB3D7EA);
39 // Load custom font with Unicode support
40 final fontData = await rootBundle.load('assets/fonts/cairo_regular_font.ttf');
41 final ttf = pw.Font.ttf(fontData);
42
43 final theme = pw.ThemeData.withFont(
44 base: ttf,
45 bold: ttf,
46 italic: ttf,
47 boldItalic: ttf,
48 );
49
50 String formatDate(DateTime? date) {
51 if (date == null) return '--';
52 return '${date.day}/${date.month}/${date.year}';
53 }
54
55 pdf.addPage(
56 pw.Page(
57 theme: theme,
58 pageFormat: PdfPageFormat.a4,
59 margin: const pw.EdgeInsets.all(20),
60 build: (context) => pw.Column(
61 crossAxisAlignment: pw.CrossAxisAlignment.start,
62 children: [
63 // Header with logo and title
64 pw.Row(
65 mainAxisAlignment: pw.MainAxisAlignment.spaceBetween,
66 children: [
67 pw.Image(logoImage, width: 80, height: 80),
68 pw.Column(
69 crossAxisAlignment: pw.CrossAxisAlignment.center,
70 children: [
71 pw.Text(
72 'Waste Electronic Manifest',
73 style: pw.TextStyle(
74 fontSize: 16,
75 fontWeight: pw.FontWeight.bold,
76 ),
77 ),
78 pw.Text(
79 '(E-Manifest)',
80 style: pw.TextStyle(
81 fontSize: 14,
82 fontWeight: pw.FontWeight.bold,
83 ),
84 ),
85 ],
86 ),
87 pw.Column(
88 crossAxisAlignment: pw.CrossAxisAlignment.end,
89 children: [
90 pw.Row(
91 children: [
92 pw.Text('Document No: ',
93 style: pw.TextStyle(fontSize: 10)),
94 pw.Text('${manifest.id}',
95 style:
96 pw.TextStyle(fontSize: 10, color: PdfColors.red)),
97 ],
98 ),
99 // pw.Text(
100 // 'Status : ${adaptstatus(status: manifest.status ?? '')}',
101 // style: pw.TextStyle(fontSize: 10),
102 // ),
103 pw.SizedBox(height: 5),
104 pw.Container(
105 width: 50,
106 height: 50,
107 child: pw.BarcodeWidget(
108 barcode: pw.Barcode.qrCode(),
109 data:
110 'WASTE E-MANIFEST - Document No: ${manifest.id} - origin: Aidra Connect',
111 ),
112 ),
113 ],
114 ),
115 ],
116 ),
117 pw.SizedBox(height: 20),
118
119 // Part A header
120 pw.Container(
121 width: double.infinity,
122 color: headerBlue,
123 padding: const pw.EdgeInsets.symmetric(vertical: 5, horizontal: 10),
124 child: pw.Text(
125 'Part - A : Waste Generator Information',
126 style: pw.TextStyle(
127 fontSize: 12,
128 fontWeight: pw.FontWeight.bold,
129 ),
130 ),
131 ),
132
133 // Generator info table
134 _buildGeneratorInfoTable(manifest),
135
136 // Transporter info
137 pw.Container(
138 padding: const pw.EdgeInsets.symmetric(horizontal: 10, vertical: 5),
139 child: pw.Column(
140 crossAxisAlignment: pw.CrossAxisAlignment.start,
141 children: [
142 pw.Text(
143 '4. Transporter\'s Name :',
144 style: pw.TextStyle(
145 fontSize: 10, fontWeight: pw.FontWeight.bold),
146 ),
147 pw.SizedBox(height: 3),
148 pw.Padding(
149 padding: const pw.EdgeInsets.only(left: 20),
150 child: pw.Column(
151 crossAxisAlignment: pw.CrossAxisAlignment.start,
152 children: [
153 pw.Text(
154 'Mailing Address:',
155 style: pw.TextStyle(fontSize: 10),
156 ),
157 pw.SizedBox(height: 3),
158 pw.Row(
159 children: [
160 pw.Expanded(
161 child: pw.Text(
162 'Tel. No:',
163 style: pw.TextStyle(fontSize: 10),
164 ),
165 ),
166 pw.Expanded(
167 child: pw.Text(
168 'Person to Contact:',
169 style: pw.TextStyle(fontSize: 10),
170 ),
171 ),
172 ],
173 ),
174 ],
175 ),
176 ),
177 ],
178 ),
179 ),
180
181 // Shipping info table
182 pw.SizedBox(height: 10),
183 _buildShippingTable(manifest),
184 pw.SizedBox(height: 15),
185
186 // Generator's certification
187 pw.Container(
188 padding: const pw.EdgeInsets.symmetric(horizontal: 10, vertical: 5),
189 child: pw.Column(
190 crossAxisAlignment: pw.CrossAxisAlignment.start,
191 children: [
192 pw.Text(
193 '10. Generator\'s Certification: I hereby declare that the containers of this consignment are fully',
194 style: pw.TextStyle(fontSize: 10),
195 ),
196 pw.Text(
197 'and accurately described above by proper shipping name and classified, packed, and labelled,',
198 style: pw.TextStyle(fontSize: 10),
199 ),
200 pw.Text(
201 'and are in all respect in proper condition for transport by highway according to applicable laws',
202 style: pw.TextStyle(fontSize: 10),
203 ),
204 pw.Text(
205 'and regulations of the kingdom.',
206 style: pw.TextStyle(fontSize: 10),
207 ),
208 pw.SizedBox(height: 15),
209 pw.Row(
210 mainAxisAlignment: pw.MainAxisAlignment.spaceBetween,
211 children: [
212 pw.Text(
213 'Name of the Authorized Representative :',
214 style: pw.TextStyle(fontSize: 10),
215 ),
216 pw.Padding(
217 padding: const pw.EdgeInsets.only(right: 50),
218 child: pw.Text(
219 'Date: ${formatDate(manifest.collectionDate)}',
220 style: pw.TextStyle(fontSize: 9)),
221 ),
222 ],
223 ),
224 pw.SizedBox(height: 8),
225 pw.Text(
226 'Signature :',
227 style: pw.TextStyle(fontSize: 10),
228 ),
229 ],
230 ),
231 ),
232
233 // Powered by footer
234 pw.Spacer(),
235 pw.Align(
236 alignment: pw.Alignment.bottomRight,
237 child: pw.Column(
238 crossAxisAlignment: pw.CrossAxisAlignment.end,
239 children: [
240 pw.Text(
241 'POWERED BY',
242 style: pw.TextStyle(fontSize: 8, color: PdfColors.grey),
243 ),
244 pw.Text(
245 'aidra®',
246 style: pw.TextStyle(fontSize: 8, color: PdfColors.grey),
247 ),
248 ],
249 ),
250 ),
251 ],
252 ),
253 ),
254 );
255
256 // Second page - matching Image 2
257 pdf.addPage(
258 pw.Page(
259 theme: theme,
260 pageFormat: PdfPageFormat.a4,
261 margin: const pw.EdgeInsets.all(20),
262 build: (context) => pw.Column(
263 crossAxisAlignment: pw.CrossAxisAlignment.start,
264 children: [
265 // Header with logo and title (same as first page)
266 pw.Row(
267 mainAxisAlignment: pw.MainAxisAlignment.spaceBetween,
268 children: [
269 pw.Image(logoImage, width: 80, height: 80),
270 pw.Column(
271 crossAxisAlignment: pw.CrossAxisAlignment.center,
272 children: [
273 pw.Text(
274 'Waste Electronic Manifest',
275 style: pw.TextStyle(
276 fontSize: 16,
277 fontWeight: pw.FontWeight.bold,
278 ),
279 ),
280 pw.Text(
281 '(E-Manifest)',
282 style: pw.TextStyle(
283 fontSize: 14,
284 fontWeight: pw.FontWeight.bold,
285 ),
286 ),
287 ],
288 ),
289 pw.Column(
290 crossAxisAlignment: pw.CrossAxisAlignment.end,
291 children: [
292 pw.Row(
293 children: [
294 pw.Text('Document No. ',
295 style: pw.TextStyle(fontSize: 10)),
296 pw.Text('${manifest.id}',
297 style:
298 pw.TextStyle(fontSize: 10, color: PdfColors.red)),
299 ],
300 ),
301 // pw.Text(
302 // 'Status : ${adaptstatus(status: manifest.status ?? '')}',
303 // style: pw.TextStyle(fontSize: 10),
304 // ),
305 pw.SizedBox(height: 5),
306 pw.Container(
307 width: 50,
308 height: 50,
309 child: pw.BarcodeWidget(
310 barcode: pw.Barcode.qrCode(),
311 data:
312 // 'WASTE E-MANIFEST - Document No: ${manifest.id} - Status: ${adaptstatus(status: manifest.status ?? '')} - origin: Aidra Connect',
313 'WASTE E-MANIFEST - Document No: ${manifest.id} - origin: Aidra Drive',
314 ),
315 ),
316 ],
317 ),
318 ],
319 ),
320 pw.SizedBox(height: 20),
321
322 // Part B header
323 pw.Container(
324 width: double.infinity,
325 color: headerBlue,
326 padding: const pw.EdgeInsets.symmetric(vertical: 5, horizontal: 10),
327 child: pw.Text(
328 'Part - B : Transporter Informations',
329 style: pw.TextStyle(
330 fontSize: 12,
331 fontWeight: pw.FontWeight.bold,
332 ),
333 ),
334 ),
335
336 // Transporter acknowledgment
337 pw.Container(
338 padding: const pw.EdgeInsets.all(10),
339 child: pw.Column(
340 crossAxisAlignment: pw.CrossAxisAlignment.start,
341 children: [
342 pw.Row(
343 mainAxisAlignment: pw.MainAxisAlignment.spaceBetween,
344 children: [
345 pw.Text(
346 '11. Transporter\'s Acknowledgment of Receipt of Materials',
347 style: pw.TextStyle(fontSize: 10),
348 ),
349 pw.Text(
350 'Date: ${formatDate(manifest.unloadingDate)}',
351 style: pw.TextStyle(fontSize: 10),
352 ),
353 ],
354 ),
355 pw.SizedBox(height: 20),
356 pw.Row(
357 mainAxisAlignment: pw.MainAxisAlignment.spaceBetween,
358 children: [
359 pw.Text(
360 'Driver Name: ${manifest.driver?.name ?? ''}',
361 style: pw.TextStyle(fontSize: 10),
362 ),
363 pw.Text(
364 'Vehicle Plate No. ${manifest.vehiclePlate ?? ''}',
365 style: pw.TextStyle(fontSize: 10),
366 ),
367 ],
368 ),
369 pw.SizedBox(height: 15),
370 pw.Text(
371 'Signature of Drive:',
372 style: pw.TextStyle(fontSize: 10),
373 ),
374 pw.SizedBox(height: 5),
375 signatureImage != null
376 ? pw.Container(
377 height: 40,
378 width: 100,
379 child: pw.Image(signatureImage),
380 )
381 : pw.Container(
382 height: 20,
383 width: 100,
384 decoration: pw.BoxDecoration(
385 border: pw.Border(
386 bottom: pw.BorderSide(color: PdfColors.black),
387 ),
388 ),
389 ),
390 ],
391 ),
392 ),
393
394 pw.SizedBox(height: 20),
395
396 // Part C header
397 pw.Container(
398 width: double.infinity,
399 color: headerBlue,
400 padding: const pw.EdgeInsets.symmetric(vertical: 5, horizontal: 10),
401 child: pw.Text(
402 'Part - C : Warehouse Facility Information',
403 style: pw.TextStyle(
404 fontSize: 12,
405 fontWeight: pw.FontWeight.bold,
406 ),
407 ),
408 ),
409
410 // Facility information
411 pw.Container(
412 padding: const pw.EdgeInsets.all(10),
413 child: pw.Column(
414 crossAxisAlignment: pw.CrossAxisAlignment.start,
415 children: [
416 pw.Text(
417 '12. Discrepancy Indication Space',
418 style: pw.TextStyle(fontSize: 10),
419 ),
420 pw.SizedBox(height: 20),
421 pw.Text(
422 '13. Facility Owner/Operator: certification of material covered by',
423 style: pw.TextStyle(fontSize: 10),
424 ),
425 pw.Text(
426 'this manifest except as noted in item',
427 style: pw.TextStyle(fontSize: 10),
428 ),
429 pw.SizedBox(height: 20),
430 pw.Row(
431 mainAxisAlignment: pw.MainAxisAlignment.spaceBetween,
432 children: [
433 pw.Text(
434 'Receiver Name',
435 style: pw.TextStyle(fontSize: 10),
436 ),
437 pw.Text(
438 'Date:',
439 style: pw.TextStyle(fontSize: 10),
440 ),
441 ],
442 ),
443 pw.SizedBox(height: 15),
444 pw.Text(
445 'Signature',
446 style: pw.TextStyle(fontSize: 10),
447 ),
448 ],
449 ),
450 ),
451
452 // Powered by footer
453 pw.Spacer(),
454 pw.Align(
455 alignment: pw.Alignment.bottomRight,
456 child: pw.Column(
457 crossAxisAlignment: pw.CrossAxisAlignment.end,
458 children: [
459 pw.Text(
460 'POWERED BY',
461 style: pw.TextStyle(fontSize: 8, color: PdfColors.grey),
462 ),
463 pw.Text(
464 'aidra®',
465 style: pw.TextStyle(fontSize: 8, color: PdfColors.grey),
466 ),
467 ],
468 ),
469 ),
470 ],
471 ),
472 ),
473 );
474
475 final output = await getTemporaryDirectory();
476 final file = File('${output.path}/e_manifest.pdf');
477 await file.writeAsBytes(await pdf.save());
478
479 OpenFile.open(file.path);
480}
481
482// Function to create the generator info table
483pw.Widget _buildGeneratorInfoTable(ManifestDocument manifest) {
484 return pw.Table(
485 border: pw.TableBorder.all(color: PdfColors.black),
486 columnWidths: {
487 0: const pw.FlexColumnWidth(1),
488 1: const pw.FlexColumnWidth(1),
489 2: const pw.FlexColumnWidth(1),
490 },
491 children: [
492 // Header row
493 pw.TableRow(
494 children: [
495 pw.Padding(
496 padding: const pw.EdgeInsets.all(5),
497 child: pw.Text(
498 '1.Generator ID. No',
499 style: pw.TextStyle(fontSize: 10),
500 ),
501 ),
502 pw.Padding(
503 padding: const pw.EdgeInsets.all(5),
504 child: pw.Text(
505 '2. Generator\'S Name',
506 style: pw.TextStyle(fontSize: 10),
507 ),
508 ),
509 pw.Padding(
510 padding: const pw.EdgeInsets.all(5),
511 child: pw.Text(
512 '3. Generator\'s Address, Phone No. and Person To Contact',
513 style: pw.TextStyle(fontSize: 10),
514 ),
515 ),
516 ],
517 ),
518 // Empty rows for data
519 ...manifest.collectionVoucher!.map((voucher) => pw.TableRow(
520 children: [
521 pw.Padding(
522 padding: const pw.EdgeInsets.all(5),
523 child: pw.Text(
524 voucher.id.toString(),
525 style: pw.TextStyle(fontSize: 10),
526 ),
527 ),
528 pw.Padding(
529 padding: const pw.EdgeInsets.all(5),
530 child: pw.Text(
531 voucher.collectionPoint ?? '',
532 style: pw.TextStyle(fontSize: 10),
533 ),
534 ),
535 pw.Padding(
536 padding: const pw.EdgeInsets.all(5),
537 child: pw.Text(
538 voucher.address ?? '',
539 style: pw.TextStyle(fontSize: 10),
540 ),
541 ),
542 ],
543 )),
544 ],
545 );
546}
547
548// Function to create the shipping info table
549pw.Widget _buildShippingTable(ManifestDocument manifest) {
550 return pw.Table(
551 border: pw.TableBorder.all(color: PdfColors.black),
552 columnWidths: {
553 0: const pw.FlexColumnWidth(3),
554 1: const pw.FlexColumnWidth(2),
555 2: const pw.FlexColumnWidth(1),
556 3: const pw.FlexColumnWidth(1),
557 4: const pw.FlexColumnWidth(1),
558 },
559 children: [
560 // Header row
561 pw.TableRow(
562 decoration: pw.BoxDecoration(color: PdfColors.blue50),
563 children: [
564 pw.Padding(
565 padding: const pw.EdgeInsets.all(5),
566 child: pw.Text(
567 '5.(Shipping Name, Hazard Class, and Pin)',
568 style: pw.TextStyle(fontSize: 9),
569 ),
570 ),
571 pw.Column(
572 children: [
573 pw.Container(
574 width: double.infinity,
575 alignment: pw.Alignment.center,
576 padding: const pw.EdgeInsets.all(5),
577 child: pw.Text(
578 '6.Containers',
579 style: pw.TextStyle(fontSize: 9),
580 ),
581 ),
582 pw.Table(
583 border: pw.TableBorder(
584 top: pw.BorderSide(color: PdfColors.black),
585 horizontalInside: pw.BorderSide(color: PdfColors.black),
586 verticalInside: pw.BorderSide(color: PdfColors.black),
587 ),
588 columnWidths: {
589 0: const pw.FlexColumnWidth(1),
590 1: const pw.FlexColumnWidth(1),
591 },
592 children: [
593 pw.TableRow(
594 children: [
595 pw.Container(
596 alignment: pw.Alignment.center,
597 padding: const pw.EdgeInsets.all(2),
598 child: pw.Text('No.', style: pw.TextStyle(fontSize: 8)),
599 ),
600 pw.Container(
601 alignment: pw.Alignment.center,
602 padding: const pw.EdgeInsets.all(2),
603 child:
604 pw.Text('Type', style: pw.TextStyle(fontSize: 8)),
605 ),
606 ],
607 ),
608 ],
609 ),
610 ],
611 ),
612 pw.Container(
613 alignment: pw.Alignment.center,
614 padding: const pw.EdgeInsets.all(5),
615 child: pw.Text(
616 '7.Total Qty',
617 style: pw.TextStyle(fontSize: 9),
618 ),
619 ),
620 pw.Container(
621 alignment: pw.Alignment.center,
622 padding: const pw.EdgeInsets.all(5),
623 child: pw.Text(
624 '8. Unit Et/Vol',
625 style: pw.TextStyle(fontSize: 9),
626 ),
627 ),
628 pw.Container(
629 alignment: pw.Alignment.center,
630 padding: const pw.EdgeInsets.all(5),
631 child: pw.Text(
632 '9.WPS No',
633 style: pw.TextStyle(fontSize: 9),
634 ),
635 ),
636 ],
637 ),
638 // Empty data row
639
640 pw.TableRow(
641 children: [
642 pw.Container(
643 padding: pw.EdgeInsets.only(left: 10),
644 height: 25,
645 child: pw.Text(manifest.productName?.get('en_US') ?? ''),
646 ),
647 pw.Table(
648 border: pw.TableBorder(
649 verticalInside: pw.BorderSide(color: PdfColors.black),
650 ),
651 columnWidths: {
652 0: const pw.FlexColumnWidth(1),
653 1: const pw.FlexColumnWidth(1),
654 },
655 children: [
656 pw.TableRow(
657 children: [
658 pw.Container(
659 height: 25,
660 padding: pw.EdgeInsets.only(left: 10),
661 child: pw.Text('${manifest.containerNumber}')),
662 pw.Container(
663 padding: pw.EdgeInsets.only(left: 10),
664 height: 25,
665 child: pw.Text('${manifest.containerType}')),
666 ],
667 ),
668 ],
669 ),
670 pw.Container(
671 padding: pw.EdgeInsets.only(left: 10),
672 height: 25,
673 child: pw.Text('${manifest.totalQuantity ?? ''}')),
674 pw.Container(
675 padding: pw.EdgeInsets.only(left: 10),
676 height: 25,
677 child: pw.Text(
678 ' L',
679 )),
680 pw.Container(
681 padding: pw.EdgeInsets.only(left: 10),
682 height: 25,
683 child: pw.Text('')),
684 ],
685 ),
686 ],
687 );
688}
class App extends StatefulWidget build(BuildContext context)
Definition app.dart:31
static const String tajmielogo
Definition assets.dart:4
final LocalizedString productName
static final UserInfoService instance
final String signature
Definition user_info.dart:5
final String signatureImage
final Widget child
final EdgeInsets padding
class Partner String
final Color color
Definition failures.dart:1
final String date
Future generateManifest(ManifestDocument manifest,) async