import 'dart:convert'; import 'dart:typed_data'; import 'package:ambito/src/entity/cart/cart_datasource.dart'; import 'package:ambito/src/entity/cart/cart_element.dart'; import 'package:ambito/src/entity/cart/cart_repository.dart'; import 'package:ambito/src/entity/measure/complete/measure_complete.dart'; import 'package:ambito/src/entity/measure/general/measure_general.dart'; import 'package:ambito/src/packages/ambito_theme/ambito_theme.dart'; import 'package:flutter/material.dart'; import 'package:flutter_to_pdf/export_delegate.dart'; import 'package:flutter_to_pdf/export_frame.dart'; import 'package:screen_breakpoints/screen_breakpoints.dart'; import 'package:screenshot/screenshot.dart'; import 'package:syncfusion_flutter_core/theme.dart'; import 'package:syncfusion_flutter_datagrid/datagrid.dart'; import 'package:syncfusion_flutter_datagrid_export/export.dart'; import 'package:syncfusion_flutter_pdf/pdf.dart'; import 'package:url_launcher/url_launcher.dart'; import '../../consts/consts.dart'; import '../../entity/_general/id_value/id_value.dart'; import '../../entity/cart/cart.dart'; import '../../entity/measure/general/measure_general_repository.dart'; import '../../widgets/buttons/print_all_button.dart'; import '../../widgets/buttons/print_button.dart'; import '../../widgets/page/base_page.dart'; class CartPage extends StatefulWidget { const CartPage({super.key, required this.measure}); final MeasureComplete? measure; @override State createState() => CartPageState(); } class CartPageState extends State { List? carts; Widget cartCards = const SizedBox(); final ExportDelegate exportDelegate = ExportDelegate( ttfFonts: { 'OpenSans': 'fonts/OpenSans-Regular.ttf', 'OpenSans_regular': 'fonts/OpenSans-Regular.ttf', 'OpenSans_500': 'fonts/OpenSans-Bold.ttf', }, ); final ScreenshotController screenshotController = ScreenshotController(); Uint8List? _imageFile; final DataGridController _dataGridController = DataGridController(); @override void initState() { super.initState(); } @override Widget build(BuildContext context) { final AmbitoTheme theme = getTheme(context); carts = CartRepository().getMyCarts(); return BasePage().getPage( context, BreakpointBuilder( builder: ( context, breakpoint, configuration, ) { return SingleChildScrollView( child: Center( child: Screenshot( controller: screenshotController, child: SizedBox( width: Breakpoint.fromContext(context).width, child: Column( mainAxisAlignment: MainAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start, children: [ theme.verticalSpacer, Text( 'Warenkorb', style: theme.headlineLarge, textAlign: TextAlign.start, ), theme.verticalSpacerSmall, Row( mainAxisSize: MainAxisSize.max, mainAxisAlignment: MainAxisAlignment.end, children: [ const Spacer(), PrintAllButton( onPressed: () async { screenshotController.capture(); }, ), ], ), theme.verticalSpacerSmall, buildCards(theme, carts), ], ), ), ), ), ); }, ), ); } Future saveFile(document, String name) async {} Widget buildCards(AmbitoTheme theme, List? carts) { List children = []; if (carts != null) { for (final cart in carts) { final measure = MeasureGeneralRepository().getByName(cart.name!); final elements = CartRepository().getElementsByCartId(cart.id); double sum = 0; final GlobalKey key = GlobalKey(); for (final element in elements) { sum = sum + ((int.tryParse(element.amount ?? '1') ?? 1) * (double.tryParse(element.price ?? '0') ?? 0)); } final card = SizedBox( width: 1152, child: Card( elevation: 0, color: theme.currentColorScheme.tertiary, child: Padding( padding: const EdgeInsets.all(20), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( children: [ Text( cart.name!, style: theme.labelLarge .copyWith(color: theme.currentColorScheme.primary), ), const Spacer(), SizedBox( height: 40, width: 200, child: ClipRRect( borderRadius: const BorderRadius.all( Radius.circular(10), ), child: measure?.getFullImage() ?? Image.asset('assets/images/logo_trans.png'), ), ), ], ), theme.verticalSpacerSmall, gridWidget(elements, key), theme.verticalSpacer, Row( children: [ Text( 'Richtpreis ca. ${sum.toStringAsFixed(2)}€', style: theme.labelMedium .copyWith(fontWeight: FontWeight.bold), ), Spacer(), PrintButton( onPressed: () async { PdfDocument document = key.currentState!.exportToPdfDocument( headerFooterExport: (DataGridPdfHeaderFooterExportDetails headerFooterExport) { final double width = headerFooterExport.pdfPage .getClientSize() .width; final PdfPageTemplateElement header = PdfPageTemplateElement( Rect.fromLTWH(0, 0, width, 65)); header.graphics.drawString( 'Warenkorb für "${cart.name!}"', PdfStandardFont(PdfFontFamily.helvetica, 13, style: PdfFontStyle.bold), bounds: const Rect.fromLTWH(0, 25, 400, 60), ); headerFooterExport.pdfDocumentTemplate.top = header; }, cellExport: (details) { if (details.cellType == DataGridExportCellType.row && details.columnName == 'Anbieter') { if (details.cellValue.toString() == '[]') { details.pdfCell.value = '-'; } else { List values = []; for (IdValue idValue in (details.cellValue as List)) { values.add(idValue.value ?? ''); } logger.d(values.join(', ')); details.pdfCell.value = values.join(', '); } } }, fitAllColumnsInOnePage: true, ); final List bytes = document.saveSync(); launchUrl(Uri.parse( "data:application/octet-stream;base64,${base64Encode(bytes)}")); }, ), ], ) ], ), ), ), ); children.add(card); children.add(theme.verticalSpacerMax); } } return ExportFrame( frameId: 'completeCart', exportDelegate: exportDelegate, child: Column( children: children, ), ); } Widget gridWidget( List cartElements, GlobalKey key) { final AmbitoTheme theme = getTheme(context); return SfDataGridTheme( data: SfDataGridThemeData( headerColor: theme.currentColorScheme.primaryContainer, sortIcon: Icon( Icons.keyboard_arrow_down, color: theme.currentColorScheme.primary, ), ), child: SfDataGrid( controller: _dataGridController, key: key, allowSorting: true, allowEditing: true, selectionMode: SelectionMode.single, editingGestureType: EditingGestureType.doubleTap, navigationMode: GridNavigationMode.cell, source: CartDataSource( cartElements: cartElements, context: context, controller: _dataGridController), columnWidthMode: ColumnWidthMode.fill, columns: [ GridColumn( columnName: 'Material', allowEditing: true, label: Container( padding: const EdgeInsets.symmetric(horizontal: 10.0), alignment: Alignment.centerLeft, child: Text( 'Material', overflow: TextOverflow.ellipsis, style: theme.bodyMedium.copyWith( color: theme.currentColorScheme.primary, ), ), ), ), GridColumn( columnName: 'Menge', maximumWidth: 150, allowEditing: true, label: Container( padding: const EdgeInsets.symmetric(horizontal: 10.0), alignment: Alignment.centerLeft, child: Text( 'Menge', overflow: TextOverflow.ellipsis, style: theme.bodyMedium.copyWith( color: theme.currentColorScheme.primary, ), ), ), ), GridColumn( columnName: 'Anbieter', maximumWidth: 200, allowSorting: false, allowEditing: false, label: Container( padding: const EdgeInsets.symmetric(horizontal: 10.0), alignment: Alignment.centerLeft, child: Text( 'Anbieter', overflow: TextOverflow.ellipsis, style: theme.bodyMedium.copyWith( color: theme.currentColorScheme.primary, ), ), ), ), GridColumn( columnName: 'Richtpreis', allowSorting: true, allowEditing: false, maximumWidth: 250, label: Container( padding: const EdgeInsets.symmetric(horizontal: 10.0), alignment: Alignment.centerLeft, child: Text( 'Richtpreis', overflow: TextOverflow.ellipsis, style: theme.bodyMedium.copyWith( color: theme.currentColorScheme.primary, ), ), ), ), ], ), ); } }