import 'dart:typed_data'; import 'dart:ui' as ui; import 'dart:io'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:flutter/widgets.dart'; import 'package:initial_folder/base_service.dart'; import 'package:initial_folder/models/history_transaction_model.dart'; import 'package:initial_folder/providers/user_info_provider.dart'; import 'package:initial_folder/size_config.dart'; import 'package:initial_folder/theme.dart'; import 'package:initial_folder/widgets/login_regist/default_button_payment.dart'; import 'package:intl/intl.dart'; import 'package:provider/provider.dart'; import 'package:flutter/rendering.dart'; import 'package:path_provider/path_provider.dart'; import 'package:permission_handler/permission_handler.dart'; import 'package:image_gallery_saver/image_gallery_saver.dart'; import 'package:initial_folder/providers/detail_invoice_provider.dart' as invProv; class Invoice extends StatefulWidget { Invoice({ super.key, this.dataHistoryTransactionModel, }); final HistoryTransactionModel? dataHistoryTransactionModel; @override State createState() => _InvoiceState(); } class _InvoiceState extends State { final GlobalKey _globalKey = GlobalKey(); bool _isDownloading = false; Future _captureAndSave() async { setState(() { _isDownloading = true; }); RenderRepaintBoundary boundary = _globalKey.currentContext!.findRenderObject() as RenderRepaintBoundary; ui.Image image = await boundary.toImage(); ByteData? byteData = await image.toByteData(format: ui.ImageByteFormat.png); Uint8List pngBytes = byteData!.buffer.asUint8List(); if (!(await Permission.storage.status.isGranted)) { await Permission.storage.request(); } final result = await ImageGallerySaver.saveImage( pngBytes, quality: 100, name: "invoice_${widget.dataHistoryTransactionModel!.orderId}", ); setState(() { _isDownloading = false; }); print(result); ScaffoldMessenger.of(context).showSnackBar( SnackBar(content: Text('Invoice sudah terdownload!')), ); } @override Widget build(BuildContext context) { var dataUser = Provider.of(context, listen: false).result; return Scaffold( appBar: AppBar( centerTitle: true, scrolledUnderElevation: 0.0, backgroundColor: Theme.of(context).colorScheme.background, title: Text( "Invoice", style: thirdTextStyle.copyWith( fontWeight: semiBold, fontSize: getProportionateScreenWidth(15), ), ), ), body: SingleChildScrollView( child: Consumer( builder: (context, invoiceProvider, child) { if (invoiceProvider.state == invProv.ResultState.loading) { return Center(child: CircularProgressIndicator()); } else if (invoiceProvider.state == invProv.ResultState.hasData) { Widget buildTextWidget() { String text = ""; if (invoiceProvider.detailInvoice![0].permataVaNumber != null) { text = "Permata Virtual Account"; } else if (invoiceProvider.detailInvoice![0].billerCode != null) { text = "Mandiri Virtual Account"; } else if (invoiceProvider.detailInvoice![0].vaNumbers != null && invoiceProvider.detailInvoice![0].vaNumbers! .any((va) => va.bank == 'bni')) { text = "BNI Virtual Account"; } else if (invoiceProvider.detailInvoice![0].vaNumbers != null && invoiceProvider.detailInvoice![0].vaNumbers! .any((va) => va.bank == 'bca')) { text = "BCA Virtual Account"; } else if (invoiceProvider.detailInvoice![0].billerCode != null) { text = "Mandiri Virtual Account"; } else if (invoiceProvider.detailInvoice![0].store == "alfamart") { text = "Alfamart"; } else if (invoiceProvider.detailInvoice![0].store == "indomaret") { text = "Indomart"; } else if (invoiceProvider.detailInvoice![0].paymentType == "credit_card") { text = "Credit Card"; } else { text = "Transaski Gratis"; } return Text( text, style: thirdTextStyle.copyWith( fontSize: getProportionateScreenWidth(11)), ); } return Center( child: Padding( padding: EdgeInsets.symmetric( horizontal: getProportionateScreenWidth(25)), child: Column( mainAxisAlignment: MainAxisAlignment.start, children: [ RepaintBoundary( key: _globalKey, child: Stack( children: [ Image.asset( Theme.of(context).colorScheme.brightness == Brightness.dark ? "assets/images/invoices_dark.png" : "assets/images/invoices.png", width: getProportionateScreenWidth(370), height: getProportionateScreenHeight(470), fit: BoxFit.fill, ), Padding( padding: EdgeInsets.only( left: getProportionateScreenWidth(25), right: getProportionateScreenWidth(25), top: getProportionateScreenHeight(70), ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text( 'Order ID', style: thirdTextStyle.copyWith( fontSize: getProportionateScreenWidth(11), ), ), Text( widget.dataHistoryTransactionModel! .orderId!, style: thirdTextStyle.copyWith( fontSize: getProportionateScreenWidth(11), ), ), ], ), SizedBox( height: getProportionateScreenHeight(5)), Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text( 'Tanggal Pembelian', style: thirdTextStyle.copyWith( fontSize: getProportionateScreenWidth(11), ), ), Text( DateFormat('E, d MMM y').format( DateTime.parse(widget .dataHistoryTransactionModel! .date .toString())), style: thirdTextStyle.copyWith( fontSize: getProportionateScreenWidth( 11)), ), ], ), SizedBox( height: getProportionateScreenHeight(10)), Row( mainAxisAlignment: MainAxisAlignment.start, children: [ Text( 'Informasi Pembeli', style: thirdTextStyle.copyWith( fontSize: getProportionateScreenWidth(11), ), ), ], ), Divider( color: secondaryColor, thickness: 0.5, height: 20, ), Text( 'Nama', style: thirdTextStyle.copyWith( fontSize: getProportionateScreenWidth(9), ), ), SizedBox( height: getProportionateScreenHeight(5)), Text( dataUser!.data[0].fullname!, style: thirdTextStyle.copyWith( fontSize: getProportionateScreenWidth(11)), ), SizedBox( height: getProportionateScreenHeight(6)), Text( 'Email', style: thirdTextStyle.copyWith( fontSize: getProportionateScreenWidth(9), ), ), SizedBox( height: getProportionateScreenHeight(5)), Text( dataUser.data[0].email!, style: thirdTextStyle.copyWith( fontSize: getProportionateScreenWidth(11)), ), SizedBox( height: getProportionateScreenHeight(10)), Text( "Kursus", style: thirdTextStyle.copyWith( fontSize: getProportionateScreenWidth(11)), ), Divider( color: secondaryColor, thickness: 0.5, height: 20, ), Column( children: widget .dataHistoryTransactionModel!.courses! .map((e) => listCourse( imageUrl: e.thumbnail, title: e.title, instructor: e.instructor, price: e.price, )) .toList(), ), SizedBox( height: getProportionateScreenHeight(15)), Text( "Informasi Pembayaran", style: thirdTextStyle.copyWith( fontSize: getProportionateScreenWidth(11)), ), Divider( color: secondaryColor, thickness: 0.5, height: 20, ), Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text( 'Metode Pembayaran', style: thirdTextStyle.copyWith( fontWeight: reguler, fontSize: getProportionateScreenWidth(10), ), ), buildTextWidget(), ], ), Divider( color: secondaryColor, thickness: 0.5, height: 20, ), Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text( 'Total Harga', style: thirdTextStyle.copyWith( fontWeight: reguler, fontSize: getProportionateScreenWidth(10), ), ), Text( 'Rp. ${NumberFormat.currency(locale: 'id', symbol: '', decimalDigits: 0).format(double.parse(invoiceProvider.detailInvoice![0].grossAmount! ?? "0"))}', style: thirdTextStyle.copyWith( fontSize: getProportionateScreenWidth( 11)), ), ], ), Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text( 'Potongan Kupon', style: thirdTextStyle.copyWith( fontWeight: reguler, fontSize: getProportionateScreenWidth(10), ), ), Text( 'Rp. ${NumberFormat.currency(locale: 'id', symbol: '', decimalDigits: 0).format(double.parse("0"))}', style: thirdTextStyle.copyWith( fontSize: getProportionateScreenWidth( 11)), ), ], ), Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text( 'Biaya Layanan', style: thirdTextStyle.copyWith( fontWeight: reguler, fontSize: getProportionateScreenWidth(10), ), ), Text( 'Rp. ${NumberFormat.currency(locale: 'id', symbol: '', decimalDigits: 0).format(double.parse("0"))}', style: thirdTextStyle.copyWith( fontSize: getProportionateScreenWidth( 11)), ), ], ), Divider( color: secondaryColor, thickness: 0.5, height: 20, ), Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text( 'Total Bayar', style: thirdTextStyle.copyWith( fontWeight: reguler, fontSize: getProportionateScreenWidth(10), ), ), Text( 'Rp. ${NumberFormat.currency(locale: 'id', symbol: '', decimalDigits: 0).format(double.parse(invoiceProvider.detailInvoice![0].grossAmount! ?? "0"))}', style: thirdTextStyle.copyWith( fontSize: getProportionateScreenWidth(13), fontWeight: semiBold, ), ), ], ), ], ), ), SizedBox(height: getProportionateScreenHeight(20)), ], ), ), SizedBox(height: getProportionateScreenHeight(15)), _isDownloading ? CircularProgressIndicator() : DefaultButtonPayment( text: "Download", press: () { _captureAndSave(); }, width: double.infinity, height: 37, isInvoice: true, ), ], ), ), ); } else if (invoiceProvider.state == invProv.ResultState.noData) { return Center(child: Text('No Data')); } else if (invoiceProvider.state == invProv.ResultState.error) { return Center(child: Text('Error')); } else { return Center(child: Text('Unexpected state')); } }, ), ), ); } Widget listCourse({ String? imageUrl, String? title, String? instructor, String? price, String? discountPrice, int? totalPrices, }) { return Container( padding: EdgeInsets.only( top: getProportionateScreenHeight(6), bottom: getProportionateScreenHeight(12), ), child: Row( mainAxisAlignment: MainAxisAlignment.start, children: [ Container( width: getProportionateScreenWidth(60), height: getProportionateScreenHeight(30), decoration: BoxDecoration( borderRadius: BorderRadius.circular(2), image: DecorationImage( image: NetworkImage(imageUrl != null && imageUrl.isNotEmpty ? "$baseUrl/uploads/thumbnail/course_thumbnails/$imageUrl" : "https://api.vokasia.id/images/default-thumbnail.png"), fit: BoxFit.cover, ), ), ), SizedBox(width: getProportionateScreenWidth(10)), Flexible( flex: 7, child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( title!, maxLines: 2, overflow: TextOverflow.ellipsis, style: thirdTextStyle.copyWith( letterSpacing: 0.5, fontWeight: reguler, fontSize: getProportionateScreenWidth(11), ), ), ], ), ), ], ), ); } }