Initial commit: Penyerahan final Source code Tugas Akhir
This commit is contained in:
491
lib/screens/profile/account_sign_in/invoice.dart
Normal file
491
lib/screens/profile/account_sign_in/invoice.dart
Normal file
@ -0,0 +1,491 @@
|
||||
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),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user