diff --git a/dart/generate_pdf/.gitignore b/dart/generate_pdf/.gitignore new file mode 100644 index 00000000..a8852f54 --- /dev/null +++ b/dart/generate_pdf/.gitignore @@ -0,0 +1,30 @@ +# See https://www.dartlang.org/guides/libraries/private-files + +# Files and directories created by pub +.dart_tool/ +.packages +build/ +# If you're building an application, you may want to check-in your pubspec.lock +pubspec.lock + +# Directory created by dartdoc +# If you don't generate documentation locally you can remove this line. +doc/api/ + +# dotenv environment variables file +.env* + +# Avoid committing generated Javascript files: +*.dart.js +*.info.json # Produced by the --dump-info flag. +*.js # When generated by dart2js. Don't specify *.js if your + # project includes source files written in JavaScript. +*.js_ +*.js.deps +*.js.map + +.flutter-plugins +.flutter-plugins-dependencies + +# Directory used by Appwrite CLI for local development +.appwrite \ No newline at end of file diff --git a/dart/generate_pdf/README.md b/dart/generate_pdf/README.md new file mode 100644 index 00000000..a8dc8b84 --- /dev/null +++ b/dart/generate_pdf/README.md @@ -0,0 +1,31 @@ +# 📄 Dart Generate PDF Function + +Generates a sample invoice in PDF. + +## 🧰 Usage + +### GET / + +Returns a PDF invoice. + +No parameters required. + +**Response** + +Sample `200` Response: + +Returns a binary stream of the generated PDF document. The `Content-Type` of the response will be set as `application/pdf`. + +## ⚙️ Configuration + +| Setting | Value | +| ----------------- | --------------- | +| Runtime | Dart (3.5.0) | +| Entrypoint | `lib/main.dart` | +| Build Commands | `dart pub get` | +| Permissions | `any` | +| Timeout (Seconds) | 15 | + +## 🔒 Environment Variables + +No environment variables required. diff --git a/dart/generate_pdf/analysis_options.yaml b/dart/generate_pdf/analysis_options.yaml new file mode 100644 index 00000000..ea2c9e94 --- /dev/null +++ b/dart/generate_pdf/analysis_options.yaml @@ -0,0 +1 @@ +include: package:lints/recommended.yaml \ No newline at end of file diff --git a/dart/generate_pdf/lib/faker.dart b/dart/generate_pdf/lib/faker.dart new file mode 100644 index 00000000..c037fd25 --- /dev/null +++ b/dart/generate_pdf/lib/faker.dart @@ -0,0 +1,23 @@ +import 'package:faker_dart/faker_dart.dart'; + +Map generateFakeOrder() { + final faker = Faker.instance; + List> items = List.generate( + faker.datatype.number(min: 1, max: 5), + (_) => { + 'description': faker.commerce.productName(), + 'quantity': faker.datatype.number(min: 1, max: 10), + 'cost': double.parse(faker.commerce.price(symbol: '')) + .toStringAsFixed(2) + }); + + return { + 'id': faker.datatype.uuid(), + 'date': faker.date.past(DateTime.now(), rangeInYears: 25).toIso8601String(), + 'name': faker.name.fullName(), + 'items': items, + 'total': items.fold(0, (sum, item) { + return sum + double.parse(item['cost']); + }) + }; +} diff --git a/dart/generate_pdf/lib/main.dart b/dart/generate_pdf/lib/main.dart new file mode 100644 index 00000000..59778797 --- /dev/null +++ b/dart/generate_pdf/lib/main.dart @@ -0,0 +1,25 @@ +import 'dart:convert'; +import './pdf.dart'; +import './faker.dart'; + +Future> pdfHandler() async { + final fakeOrder = generateFakeOrder(); + print( + 'Generated fake order: ${JsonEncoder.withIndent(' ').convert(fakeOrder)}'); + + final pdfBuffer = await createPDF(fakeOrder); + print('PDF created'); + + return pdfBuffer; +} + +Future main(final context) async { + try { + final pdfBuffer = await pdfHandler(); + return context.res + .binary(pdfBuffer, 200, {'Content-Type': 'application/pdf'}); + } catch (e) { + context.error('Error occurred while generating PDF: $e'); + return context.res.text('Error occurred while generating PDF: $e', 500); + } +} diff --git a/dart/generate_pdf/lib/pdf.dart b/dart/generate_pdf/lib/pdf.dart new file mode 100644 index 00000000..dfc771cd --- /dev/null +++ b/dart/generate_pdf/lib/pdf.dart @@ -0,0 +1,61 @@ +import 'dart:typed_data'; +import 'package:pdf/pdf.dart'; +import 'package:pdf/widgets.dart' as pw; + +Future createPDF(order) async { + final pdf = pw.Document(); + final date = DateTime.parse(order['date']); + + final String orderList = (order['items'] as List) + .map((item) => + '${item['description']} x ${item['quantity']} = \$${item['cost']}') + .join('\n'); + + pdf.addPage(pw.Page( + pageFormat: PdfPageFormat.a4, + margin: pw.EdgeInsets.only(left: 50), + build: (pw.Context context) { + return pw.Stack(children: [ + // Invoice title + pw.Positioned( + bottom: 750, + child: + pw.Text('Sample Invoice', style: pw.TextStyle(fontSize: 20))), + + // Order date + pw.Positioned( + left: 350, + bottom: 750, + child: pw.Text('${date.month}/${date.day}/${date.year}', + style: pw.TextStyle(fontSize: 15))), + + // Name + pw.Positioned( + bottom: 700, + child: pw.Text('Hello, ${order['name']}!', + style: pw.TextStyle(fontSize: 30))), + + // Order ID + pw.Positioned( + bottom: 650, + child: pw.Text('Order ID: ${order['id']}', + style: pw.TextStyle(fontSize: 10))), + + // Order total + pw.Positioned( + bottom: 600, + child: pw.Text('Total: \$${order['total'].toStringAsFixed(2)}', + style: pw.TextStyle(fontSize: 15))), + + // Order item list + pw.Positioned( + top: 841.89 - 565, + child: pw.Text(orderList, + style: pw.TextStyle(fontSize: 15, lineSpacing: 8))), + ]); + })); + + final Uint8List pdfBytes = await pdf.save(); + + return Uint8List.fromList(pdfBytes); +} diff --git a/dart/generate_pdf/pubspec.yaml b/dart/generate_pdf/pubspec.yaml new file mode 100644 index 00000000..465fd773 --- /dev/null +++ b/dart/generate_pdf/pubspec.yaml @@ -0,0 +1,15 @@ +name: generate_pdf +version: 1.0.0 + +environment: + sdk: ^3.5.0 + +dependencies: + dart_appwrite: ^13.0.0 + faker_dart: ^0.2.2 + pdf: ^3.11.3 + shelf: ^1.4.2 + +dev_dependencies: + lints: ^5.0.0 + test: ^1.24.0