492 lines
22 KiB
Dart
492 lines
22 KiB
Dart
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<Invoice> createState() => _InvoiceState();
|
|
}
|
|
|
|
class _InvoiceState extends State<Invoice> {
|
|
final GlobalKey _globalKey = GlobalKey();
|
|
bool _isDownloading = false;
|
|
|
|
Future<void> _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<UserInfoProvider>(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<invProv.DetailInvoiceProvider>(
|
|
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),
|
|
),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
],
|
|
),
|
|
);
|
|
}
|
|
}
|