diff --git a/lib/pages/print/print_controller.dart b/lib/pages/print/print_controller.dart new file mode 100644 index 0000000..8fa58e8 --- /dev/null +++ b/lib/pages/print/print_controller.dart @@ -0,0 +1,103 @@ +import 'package:get/get.dart'; +import 'package:pdf/pdf.dart'; +import 'package:pdf/widgets.dart' as pw; +import 'package:printing/printing.dart'; + +import '../../data/models/tank_model.dart'; +import '../tanklist/tanklist_view.dart'; + +class PrintController extends GetxController { + final argunments = Get.arguments; + final List tankList = Get.arguments['tankList'] ?? []; + final String year = Get.arguments['year'] ?? 'NoYear'; + final String summeLiter = Get.arguments['summeLiter'] ?? '0.0'; + final String summePreis = Get.arguments['summePreis'] ?? '0.0'; + + Future printPdfReport() async { + final doc = pw.Document(); + final font = await PdfGoogleFonts.robotoRegular(); + final List tankungen = + tankList.map((e) => AppWriteTankModel.fromMap(e)).toList(); + + doc.addPage( + pw.Page( + pageFormat: PdfPageFormat.a4, + build: (pw.Context context) { + return pw.Column( + crossAxisAlignment: pw.CrossAxisAlignment.start, + children: [ + // PDF-Design hier + pw.Text('Tankbericht $year', + style: pw.TextStyle( + fontSize: 24, + fontWeight: pw.FontWeight.bold, + color: PdfColors.blue900, + font: font)), + pw.SizedBox(height: 10), + pw.Text('Alle Tankungen im Überblick', + style: pw.TextStyle( + fontSize: 16, color: PdfColors.grey700, font: font)), + pw.Divider(color: PdfColors.grey400), + pw.SizedBox(height: 20), + + pw.TableHelper.fromTextArray( + headers: [ + 'Datum', + 'Ort', + 'Menge (L)', + 'Preis/L (€)', + 'Summe (€)' + ], + cellAlignment: pw.Alignment.centerLeft, + border: pw.TableBorder.all(color: PdfColors.grey200), + headerStyle: + pw.TextStyle(fontWeight: pw.FontWeight.bold, font: font), + data: tankungen.map((item) { + var modDate = item.date.substring(5); + return [ + modDate, + item.location, + item.liters, + item.pricePerLiter, + item.szSummePreis ?? '0.0', + ]; + }).toList(), + ), + + pw.Spacer(), + pw.Divider(color: PdfColors.grey400), + pw.Container( + alignment: pw.Alignment.centerRight, + child: pw.Column( + crossAxisAlignment: pw.CrossAxisAlignment.end, + children: [ + pw.Text('Jahres-Gesamtmenge: $summeLiter L', + style: pw.TextStyle( + fontWeight: pw.FontWeight.bold, + fontSize: 16, + font: font)), + pw.Text('Jahres-Gesamtsumme: $summePreis €', + style: pw.TextStyle( + fontWeight: pw.FontWeight.bold, + fontSize: 16, + color: PdfColors.blue700, + font: font)), + ], + ), + ), + ], + ); + }, + ), + ); + + // Druckansicht öffnen + await Printing.layoutPdf( + onLayout: (PdfPageFormat format) async => doc.save(), + ); + } + + void goToTankListPage() async { + await Get.offAndToNamed(TanklistPage.namedRoute); + } +} diff --git a/lib/pages/print/print_view.dart b/lib/pages/print/print_view.dart new file mode 100644 index 0000000..04934a6 --- /dev/null +++ b/lib/pages/print/print_view.dart @@ -0,0 +1,40 @@ +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; +import './print_controller.dart'; + +class PrintPage extends GetView { + static const namedRoute = '/print-pdf-page'; + const PrintPage({super.key}); + + @override + Widget build(BuildContext context) { + var printCtrl = controller; + return PopScope( + canPop: false, + child: SafeArea( + child: Scaffold( + appBar: AppBar( + title: const Text('PDF-Bericht'), + centerTitle: true, + actions: [ + IconButton( + icon: const Icon(Icons.list, color: Colors.white), + onPressed: () { + // Handle logout logic here + printCtrl.goToTankListPage(); + }, + ), + ], + ), + body: Center( + child: ElevatedButton( + // Ruft die Controller-Methode auf + onPressed: () => printCtrl.printPdfReport(), + child: const Text('PDF erstellen & drucken'), + ), + ), + ), + ), + ); + } +} diff --git a/lib/pages/tanklist/tanklist_controller.dart b/lib/pages/tanklist/tanklist_controller.dart index 73b525e..67530fd 100644 --- a/lib/pages/tanklist/tanklist_controller.dart +++ b/lib/pages/tanklist/tanklist_controller.dart @@ -8,6 +8,7 @@ import '../../data/models/tank_model.dart'; import '../../data/repository/appwrite_repository.dart'; import '../../pages/tank/tank_view.dart'; import '../../pages/gaslist/gaslist_view.dart'; +import '../print/print_view.dart'; class TanklistController extends GetxController { final _dataBox = GetStorage('MyUserStorage'); @@ -164,4 +165,15 @@ class TanklistController extends GetxController { await Get.offAndToNamed(GaslistPage.namedRoute); } + + void goToPrintView() { + + List> tankMap = rxTankListActualYear.map((e) => e.toMap()).toList(); + Get.offAndToNamed(PrintPage.namedRoute, arguments: { + 'tankList': tankMap, + 'year': szRxYear.value, + 'summeLiter': szRxSummeYearLiter.value, + 'summePreis': szRxSummePrice.value, + }); + } } diff --git a/lib/pages/tanklist/tanklist_view.dart b/lib/pages/tanklist/tanklist_view.dart index 5c7c20a..c3f8119 100644 --- a/lib/pages/tanklist/tanklist_view.dart +++ b/lib/pages/tanklist/tanklist_view.dart @@ -34,6 +34,14 @@ class TanklistPage extends GetView { tankListCtrl.goToGasView(); }, ), + IconButton( + icon: Icon(Icons.print, + color: Colors.grey.shade300), + onPressed: () async { + // Handle go to Chart View + tankListCtrl.goToPrintView(); + }, + ), IconButton( icon: Icon(Icons.logout, color: Colors.grey.shade300), onPressed: () async { @@ -140,12 +148,11 @@ class TanklistPage extends GetView { ); }), itemCount: tankListCtrl.rxTankListActualYear.length, - ):Expanded(child: Center( + ): Center( child: Text('Keine Einträge für das aktuelle Jahr vorhanden', style: TextStyle( fontSize: 18, color: Colors.grey.shade600)), - ), - ) + ), ), ], ), diff --git a/lib/utils/extensions/sample_bindings.dart b/lib/utils/extensions/sample_bindings.dart index a49e314..cea53bf 100644 --- a/lib/utils/extensions/sample_bindings.dart +++ b/lib/utils/extensions/sample_bindings.dart @@ -5,20 +5,17 @@ import '../../pages/graph/graph_controller.dart'; import '../../pages/login/login_controller.dart'; import '../../pages/tank/tank_controller.dart'; import '../../pages/tanklist/tanklist_controller.dart'; - - +import '../../pages/print/print_controller.dart'; class SampleBindings extends Bindings { @override void dependencies() { // Define your dependencies here - Get.lazyPut(() => LoginController()); - Get.lazyPut(() => TankController()); - Get.lazyPut(() => TanklistController()); - Get.lazyPut(() => GraphController()); - Get.lazyPut(() => GaslistController()); - // Get.lazyPut(() => TrackingController(AuthRepository(AppWriteProvider()))); - // Get.lazyPut(() => MapController(AuthRepository(AppWriteProvider()), LocationRepository(LocationProvider()))); + Get.lazyPut(() => LoginController()); + Get.lazyPut(() => TankController()); + Get.lazyPut(() => TanklistController()); + Get.lazyPut(() => GraphController()); + Get.lazyPut(() => GaslistController()); + Get.lazyPut(() => PrintController()); } - -} \ No newline at end of file +} diff --git a/lib/utils/extensions/sample_routes.dart b/lib/utils/extensions/sample_routes.dart index 0ab0417..df7834a 100644 --- a/lib/utils/extensions/sample_routes.dart +++ b/lib/utils/extensions/sample_routes.dart @@ -2,6 +2,7 @@ import 'package:get/get.dart'; import '../../pages/graph/graph_view.dart'; import '../../pages/login/login_view.dart'; +import '../../pages/print/print_view.dart'; import '../../pages/tank/tank_view.dart'; import '../../pages/tanklist/tanklist_view.dart'; import '../../pages/gaslist/gaslist_view.dart'; @@ -37,6 +38,11 @@ class SampleRouts { page: () => const GaslistPage(), binding: sampleBindings, ), + GetPage( + name: PrintPage.namedRoute, + page: () => const PrintPage(), + binding: sampleBindings, + ), // GetPage( // name: MapPage.namedRoute, // page: () => const MapPage(), diff --git a/linux/flutter/generated_plugin_registrant.cc b/linux/flutter/generated_plugin_registrant.cc index a66595a..2561f03 100644 --- a/linux/flutter/generated_plugin_registrant.cc +++ b/linux/flutter/generated_plugin_registrant.cc @@ -7,6 +7,7 @@ #include "generated_plugin_registrant.h" #include +#include #include #include #include @@ -16,6 +17,9 @@ void fl_register_plugins(FlPluginRegistry* registry) { g_autoptr(FlPluginRegistrar) desktop_webview_window_registrar = fl_plugin_registry_get_registrar_for_plugin(registry, "DesktopWebviewWindowPlugin"); desktop_webview_window_plugin_register_with_registrar(desktop_webview_window_registrar); + g_autoptr(FlPluginRegistrar) printing_registrar = + fl_plugin_registry_get_registrar_for_plugin(registry, "PrintingPlugin"); + printing_plugin_register_with_registrar(printing_registrar); g_autoptr(FlPluginRegistrar) screen_retriever_linux_registrar = fl_plugin_registry_get_registrar_for_plugin(registry, "ScreenRetrieverLinuxPlugin"); screen_retriever_linux_plugin_register_with_registrar(screen_retriever_linux_registrar); diff --git a/linux/flutter/generated_plugins.cmake b/linux/flutter/generated_plugins.cmake index febb7dd..c3c2d88 100644 --- a/linux/flutter/generated_plugins.cmake +++ b/linux/flutter/generated_plugins.cmake @@ -4,6 +4,7 @@ list(APPEND FLUTTER_PLUGIN_LIST desktop_webview_window + printing screen_retriever_linux url_launcher_linux window_manager diff --git a/macos/Flutter/GeneratedPluginRegistrant.swift b/macos/Flutter/GeneratedPluginRegistrant.swift index 3c11380..79fa4d7 100644 --- a/macos/Flutter/GeneratedPluginRegistrant.swift +++ b/macos/Flutter/GeneratedPluginRegistrant.swift @@ -11,6 +11,7 @@ import flutter_web_auth_2 import geolocator_apple import package_info_plus import path_provider_foundation +import printing import screen_retriever_macos import url_launcher_macos import window_manager @@ -23,6 +24,7 @@ func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) { GeolocatorPlugin.register(with: registry.registrar(forPlugin: "GeolocatorPlugin")) FPPPackageInfoPlusPlugin.register(with: registry.registrar(forPlugin: "FPPPackageInfoPlusPlugin")) PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin")) + PrintingPlugin.register(with: registry.registrar(forPlugin: "PrintingPlugin")) ScreenRetrieverMacosPlugin.register(with: registry.registrar(forPlugin: "ScreenRetrieverMacosPlugin")) UrlLauncherPlugin.register(with: registry.registrar(forPlugin: "UrlLauncherPlugin")) WindowManagerPlugin.register(with: registry.registrar(forPlugin: "WindowManagerPlugin")) diff --git a/pubspec.lock b/pubspec.lock index 4fb8e19..233bd3f 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -41,6 +41,22 @@ packages: url: "https://pub.dev" source: hosted version: "2.11.0" + barcode: + dependency: transitive + description: + name: barcode + sha256: "7b6729c37e3b7f34233e2318d866e8c48ddb46c1f7ad01ff7bb2a8de1da2b9f4" + url: "https://pub.dev" + source: hosted + version: "2.2.9" + bidi: + dependency: transitive + description: + name: bidi + sha256: "77f475165e94b261745cf1032c751e2032b8ed92ccb2bf5716036db79320637d" + url: "https://pub.dev" + source: hosted + version: "2.0.13" characters: dependency: transitive description: @@ -403,6 +419,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.9.0" + path_parsing: + dependency: transitive + description: + name: path_parsing + sha256: "883402936929eac138ee0a45da5b0f2c80f89913e6dc3bf77eb65b84b409c6ca" + url: "https://pub.dev" + source: hosted + version: "1.1.0" path_provider: dependency: transitive description: @@ -451,6 +475,22 @@ packages: url: "https://pub.dev" source: hosted version: "2.3.0" + pdf: + dependency: "direct main" + description: + name: pdf + sha256: "28eacad99bffcce2e05bba24e50153890ad0255294f4dd78a17075a2ba5c8416" + url: "https://pub.dev" + source: hosted + version: "3.11.3" + pdf_widget_wrapper: + dependency: transitive + description: + name: pdf_widget_wrapper + sha256: c930860d987213a3d58c7ec3b7ecf8085c3897f773e8dc23da9cae60a5d6d0f5 + url: "https://pub.dev" + source: hosted + version: "1.0.4" petitparser: dependency: transitive description: @@ -483,6 +523,22 @@ packages: url: "https://pub.dev" source: hosted version: "6.0.1" + printing: + dependency: "direct main" + description: + name: printing + sha256: "482cd5a5196008f984bb43ed0e47cbfdca7373490b62f3b27b3299275bf22a93" + url: "https://pub.dev" + source: hosted + version: "5.14.2" + qr: + dependency: transitive + description: + name: qr + sha256: "5a1d2586170e172b8a8c8470bbbffd5eb0cd38a66c0d77155ea138d3af3a4445" + url: "https://pub.dev" + source: hosted + version: "3.0.2" screen_retriever: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index 4546c0c..a55376a 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -8,21 +8,23 @@ environment: sdk: ^3.5.4 dependencies: - flutter_launcher_icons: ^0.14.3 appwrite: ^14.0.0 cupertino_icons: ^1.0.8 + fl_chart: ^1.0.0 flutter: sdk: flutter flutter_dotenv: ^5.2.1 - intl: ^0.20.2 - url_launcher: ^6.3.1 - window_manager: ^0.4.3 + flutter_launcher_icons: ^0.14.3 geolocator: ^13.0.1 get: ^4.6.6 get_storage: ^2.1.1 http: ^1.4.0 + intl: ^0.20.2 latlong2: ^0.9.1 - fl_chart: ^1.0.0 + pdf: ^3.11.3 + printing: ^5.14.2 + url_launcher: ^6.3.1 + window_manager: ^0.4.3 dependency_overrides: flutter_web_auth_2: 4.1.0 diff --git a/windows/flutter/generated_plugin_registrant.cc b/windows/flutter/generated_plugin_registrant.cc index 3a4fbf2..7b1bde6 100644 --- a/windows/flutter/generated_plugin_registrant.cc +++ b/windows/flutter/generated_plugin_registrant.cc @@ -8,6 +8,7 @@ #include #include +#include #include #include #include @@ -18,6 +19,8 @@ void RegisterPlugins(flutter::PluginRegistry* registry) { registry->GetRegistrarForPlugin("DesktopWebviewWindowPlugin")); GeolocatorWindowsRegisterWithRegistrar( registry->GetRegistrarForPlugin("GeolocatorWindows")); + PrintingPluginRegisterWithRegistrar( + registry->GetRegistrarForPlugin("PrintingPlugin")); ScreenRetrieverWindowsPluginCApiRegisterWithRegistrar( registry->GetRegistrarForPlugin("ScreenRetrieverWindowsPluginCApi")); UrlLauncherWindowsRegisterWithRegistrar( diff --git a/windows/flutter/generated_plugins.cmake b/windows/flutter/generated_plugins.cmake index 3dd5f71..03d0dad 100644 --- a/windows/flutter/generated_plugins.cmake +++ b/windows/flutter/generated_plugins.cmake @@ -5,6 +5,7 @@ list(APPEND FLUTTER_PLUGIN_LIST desktop_webview_window geolocator_windows + printing screen_retriever_windows url_launcher_windows window_manager