Initial commit
This commit is contained in:
472
app_code/lib/screens/order/order_details.dart
Normal file
472
app_code/lib/screens/order/order_details.dart
Normal file
@@ -0,0 +1,472 @@
|
||||
import 'package:dotted_line/dotted_line.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:grostore/app_lang.dart';
|
||||
import 'package:grostore/configs/style_config.dart';
|
||||
import 'package:grostore/configs/theme_config.dart';
|
||||
import 'package:grostore/custom_ui/BoxDecorations.dart';
|
||||
import 'package:grostore/custom_ui/Button.dart';
|
||||
import 'package:grostore/custom_ui/common_appbar.dart';
|
||||
import 'package:grostore/custom_ui/order_item.dart';
|
||||
import 'package:grostore/helpers/device_info_helper.dart';
|
||||
import 'package:grostore/presenters/order_details_presenter.dart';
|
||||
import 'package:grostore/screens/order/pdf_api.dart';
|
||||
import 'package:grostore/screens/order/pdf_invoice_api.dart';
|
||||
|
||||
import '../../helpers/common_functions.dart';
|
||||
|
||||
class OrderDetails extends StatefulWidget {
|
||||
final code;
|
||||
|
||||
const OrderDetails({super.key, this.code});
|
||||
|
||||
@override
|
||||
State<OrderDetails> createState() => _OrderDetailsState();
|
||||
}
|
||||
|
||||
class _OrderDetailsState extends State<OrderDetails> {
|
||||
OrderDetailsPresenter orderDetailsPresenter = OrderDetailsPresenter();
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
|
||||
orderDetailsPresenter.initState(widget.code);
|
||||
});
|
||||
super.initState();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
backgroundColor: ThemeConfig.xxlightGrey,
|
||||
appBar: CommonAppbar.show(
|
||||
title: AppLang.local(context).order_details, context: context),
|
||||
body: ListenableBuilder(
|
||||
listenable: orderDetailsPresenter,
|
||||
builder: (context, child) {
|
||||
return RefreshIndicator(
|
||||
onRefresh: () {
|
||||
return orderDetailsPresenter.onRefresh(widget.code);
|
||||
},
|
||||
child: SingleChildScrollView(
|
||||
child: orderDetailsPresenter.isInitDetails
|
||||
? Container(
|
||||
padding: EdgeInsets.symmetric(
|
||||
horizontal: StyleConfig.padding),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
const SizedBox(height: 24),
|
||||
Container(
|
||||
width: getWidth(context),
|
||||
decoration: BoxDecorations.shadow(radius: 8),
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: 8, vertical: 8),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
"Buyurtma raqami: ${orderDetailsPresenter.orderInfo?.code ?? ''}",
|
||||
style: StyleConfig.fs14fwBold,
|
||||
),
|
||||
const SizedBox(
|
||||
height: 14,
|
||||
),
|
||||
Text(
|
||||
"Buyurtma sanasi: ${orderDetailsPresenter.orderInfo?.date ?? ''}",
|
||||
style: StyleConfig.fs14fwBold,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
const SizedBox(
|
||||
height: 14,
|
||||
),
|
||||
Text(
|
||||
"Billing Address",
|
||||
style: StyleConfig.fs14fwBold,
|
||||
),
|
||||
const SizedBox(
|
||||
height: 8,
|
||||
),
|
||||
Container(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: 8, vertical: 8),
|
||||
decoration: BoxDecorations.shadow(radius: 8),
|
||||
child: buildBillingAddress(context)),
|
||||
const SizedBox(
|
||||
height: 14,
|
||||
),
|
||||
Text(
|
||||
"Shipping Address",
|
||||
style: StyleConfig.fs14fwBold,
|
||||
),
|
||||
const SizedBox(
|
||||
height: 8,
|
||||
),
|
||||
Container(
|
||||
decoration: BoxDecorations.shadow(radius: 8),
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: 8, vertical: 8),
|
||||
child: buildShippingAddress(context)),
|
||||
const SizedBox(
|
||||
height: 14,
|
||||
),
|
||||
Text(
|
||||
"Products",
|
||||
style: StyleConfig.fs14fwBold,
|
||||
),
|
||||
const SizedBox(
|
||||
height: 8,
|
||||
),
|
||||
Container(
|
||||
//decoration: BoxDecorations.shadow(radius: 8),
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: 8, vertical: 8),
|
||||
child: Column(
|
||||
children: [
|
||||
/*Row(
|
||||
|
||||
children: [
|
||||
Container(
|
||||
width: getWidth(context)*0.35,
|
||||
child: Text("Product Name")),
|
||||
Container(
|
||||
width: getWidth(context)*0.18,
|
||||
child: Text("Unit Price")),
|
||||
Container(
|
||||
width: getWidth(context)*0.1,
|
||||
child: Text("QTY")),
|
||||
Container(
|
||||
width: getWidth(context)*0.18,
|
||||
child: Text("Total Price")),
|
||||
],
|
||||
),
|
||||
Divider(color: ThemeConfig.fontColor,),*/
|
||||
GridView.builder(
|
||||
//padding: EdgeInsets.only(left: StyleConfig.padding,right: StyleConfig.padding,bottom: 20),
|
||||
shrinkWrap: true,
|
||||
physics:
|
||||
const NeverScrollableScrollPhysics(),
|
||||
gridDelegate:
|
||||
const SliverGridDelegateWithFixedCrossAxisCount(
|
||||
crossAxisCount: 2,
|
||||
crossAxisSpacing: 16,
|
||||
mainAxisSpacing: 8,
|
||||
childAspectRatio: 0.62),
|
||||
itemBuilder: (context, index) =>
|
||||
OrderItem(
|
||||
context: context,
|
||||
onReq: (value) {
|
||||
if (value) {
|
||||
orderDetailsPresenter
|
||||
.onRefresh(widget.code);
|
||||
}
|
||||
},
|
||||
item: orderDetailsPresenter
|
||||
.orderInfo!.items[index],
|
||||
)
|
||||
/*Container(
|
||||
child: Row(
|
||||
|
||||
children: [
|
||||
Container(
|
||||
width: getWidth(context)*0.35,
|
||||
child: Text(orderDetailsPresenter.orderInfo?.items[index].product?.name??"")),
|
||||
Container(
|
||||
width: getWidth(context)*0.18,
|
||||
child: Text(showPrice(orderDetailsPresenter.orderInfo?.items[index].unitPrice??""))),
|
||||
Container(
|
||||
width: getWidth(context)*0.1,
|
||||
child: Text("${orderDetailsPresenter.orderInfo?.items[index].qty??''}")),
|
||||
Container(
|
||||
width: getWidth(context)*0.18,
|
||||
child: Text(showPrice(orderDetailsPresenter.orderInfo?.items[index].totalPrice??""))),
|
||||
],
|
||||
),
|
||||
),
|
||||
,
|
||||
separatorBuilder: (context, index) => Column(
|
||||
children: [
|
||||
SizedBox(
|
||||
height: 15,
|
||||
),
|
||||
Divider(color: ThemeConfig.fontColor,),
|
||||
],
|
||||
)*/
|
||||
,
|
||||
itemCount: orderDetailsPresenter
|
||||
.orderInfo?.items.length ??
|
||||
0),
|
||||
],
|
||||
),
|
||||
),
|
||||
const SizedBox(
|
||||
height: 14,
|
||||
),
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Text(
|
||||
"Payment Method",
|
||||
style: StyleConfig.fs14fwBold,
|
||||
),
|
||||
Text(
|
||||
orderDetailsPresenter
|
||||
.orderInfo?.payment_method
|
||||
.toUpperCase() ??
|
||||
"",
|
||||
style: StyleConfig.fs14fwNormal,
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(
|
||||
height: 14,
|
||||
),
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Text(
|
||||
"Sub Total",
|
||||
style: StyleConfig.fs14fwBold,
|
||||
),
|
||||
Text(
|
||||
showPrice(orderDetailsPresenter
|
||||
.orderInfo?.subTotalAmount ??
|
||||
""),
|
||||
style: StyleConfig.fs14fwNormal,
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(
|
||||
height: 14,
|
||||
),
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Text(
|
||||
"Tips",
|
||||
style: StyleConfig.fs14fwBold,
|
||||
),
|
||||
Text(
|
||||
showPrice(orderDetailsPresenter
|
||||
.orderInfo?.totalTips ??
|
||||
""),
|
||||
style: StyleConfig.fs14fwNormal,
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(
|
||||
height: 14,
|
||||
),
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Text(
|
||||
"Shipping Cost",
|
||||
style: StyleConfig.fs14fwBold,
|
||||
),
|
||||
Text(
|
||||
showPrice(orderDetailsPresenter
|
||||
.orderInfo?.totalShippingCost ??
|
||||
""),
|
||||
style: StyleConfig.fs14fwNormal,
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(
|
||||
height: 14,
|
||||
),
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Text(
|
||||
"Coupon Discount",
|
||||
style: StyleConfig.fs14fwBold,
|
||||
),
|
||||
Text(
|
||||
showPrice(orderDetailsPresenter
|
||||
.orderInfo?.couponDiscountAmount ??
|
||||
""),
|
||||
style: StyleConfig.fs14fwNormal,
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(
|
||||
height: 14,
|
||||
),
|
||||
const DottedLine(),
|
||||
const SizedBox(
|
||||
height: 14,
|
||||
),
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Text(
|
||||
"Total Price",
|
||||
style: StyleConfig.fs14fwBold,
|
||||
),
|
||||
Text(
|
||||
showPrice(orderDetailsPresenter
|
||||
.orderInfo?.totalPrice ??
|
||||
""),
|
||||
style: StyleConfig.fs14fwBold
|
||||
.copyWith(color: ThemeConfig.red),
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(
|
||||
height: 24,
|
||||
),
|
||||
Button(
|
||||
minHeight: 40.0,
|
||||
shape: StyleConfig.buttonRadius(10),
|
||||
minWidth: MediaQuery.sizeOf(context).width,
|
||||
color: ThemeConfig.red,
|
||||
child: Text(
|
||||
AppLang.local(context).download_invoice,
|
||||
style: StyleConfig.fs14cWhitefwBold,
|
||||
),
|
||||
onPressed: () async {
|
||||
final pdf = await PdfInvoiceApi.generate(orderDetailsPresenter.orderInfo);
|
||||
PdfApi.openFile(pdf);
|
||||
},
|
||||
),
|
||||
const SizedBox(
|
||||
height: 30,
|
||||
)
|
||||
],
|
||||
),
|
||||
)
|
||||
: SizedBox(
|
||||
height: getHeight(context),
|
||||
child:
|
||||
const Center(child: CircularProgressIndicator())),
|
||||
),
|
||||
);
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
Column buildBillingAddress(BuildContext context) {
|
||||
return Column(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
orderDetailsPresenter.orderInfo?.billingAddress?.address ?? "",
|
||||
style: StyleConfig.fs14fwNormal,
|
||||
maxLines: 1,
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(top: 5.0),
|
||||
child: Row(
|
||||
children: [
|
||||
Text(
|
||||
"${AppLang.local(context).city}: ",
|
||||
style: StyleConfig.fs14fwBold,
|
||||
),
|
||||
Text(
|
||||
orderDetailsPresenter.orderInfo?.billingAddress?.cityName ?? "",
|
||||
style: StyleConfig.fs14fwNormal,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(top: 5.0),
|
||||
child: Row(
|
||||
children: [
|
||||
Text(
|
||||
"${AppLang.local(context).state}: ",
|
||||
style: StyleConfig.fs14fwBold,
|
||||
),
|
||||
Text(
|
||||
orderDetailsPresenter.orderInfo?.billingAddress?.stateName ??
|
||||
"",
|
||||
style: StyleConfig.fs14fwNormal,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(top: 5.0),
|
||||
child: Row(
|
||||
children: [
|
||||
Text(
|
||||
"${AppLang.local(context).country}: ",
|
||||
style: StyleConfig.fs14fwBold,
|
||||
),
|
||||
Text(
|
||||
orderDetailsPresenter.orderInfo?.billingAddress?.countryName ??
|
||||
"",
|
||||
style: StyleConfig.fs14fwNormal,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
Column buildShippingAddress(BuildContext context) {
|
||||
return Column(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
orderDetailsPresenter.orderInfo?.shippingAddress?.address ?? "",
|
||||
style: StyleConfig.fs14fwNormal,
|
||||
maxLines: 1,
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(top: 5.0),
|
||||
child: Row(
|
||||
children: [
|
||||
Text(
|
||||
"${AppLang.local(context).city}: ",
|
||||
style: StyleConfig.fs14fwBold,
|
||||
),
|
||||
Text(
|
||||
orderDetailsPresenter.orderInfo?.shippingAddress?.cityName ??
|
||||
"",
|
||||
style: StyleConfig.fs14fwNormal,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(top: 5.0),
|
||||
child: Row(
|
||||
children: [
|
||||
Text(
|
||||
"${AppLang.local(context).state}: ",
|
||||
style: StyleConfig.fs14fwBold,
|
||||
),
|
||||
Text(
|
||||
orderDetailsPresenter.orderInfo?.shippingAddress?.stateName ??
|
||||
"",
|
||||
style: StyleConfig.fs14fwNormal,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(top: 5.0),
|
||||
child: Row(
|
||||
children: [
|
||||
Text(
|
||||
"${AppLang.local(context).country}: ",
|
||||
style: StyleConfig.fs14fwBold,
|
||||
),
|
||||
Text(
|
||||
orderDetailsPresenter.orderInfo?.shippingAddress?.countryName ??
|
||||
"",
|
||||
style: StyleConfig.fs14fwNormal,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
148
app_code/lib/screens/order/orders.dart
Normal file
148
app_code/lib/screens/order/orders.dart
Normal file
@@ -0,0 +1,148 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:grostore/app_lang.dart';
|
||||
import 'package:grostore/configs/style_config.dart';
|
||||
import 'package:grostore/configs/theme_config.dart';
|
||||
import 'package:grostore/custom_ui/Button.dart';
|
||||
import 'package:grostore/custom_ui/common_appbar.dart';
|
||||
import 'package:grostore/custom_ui/order_view_model.dart';
|
||||
import 'package:grostore/custom_ui/shimmers.dart';
|
||||
import 'package:grostore/helpers/device_info_helper.dart';
|
||||
import 'package:grostore/helpers/route.dart';
|
||||
import 'package:grostore/presenters/order_presenter.dart';
|
||||
import 'package:grostore/screens/main.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
class Orders extends StatefulWidget {
|
||||
bool fromBottomBar;
|
||||
bool fromCheckOut;
|
||||
|
||||
Orders({Key? key, this.fromBottomBar = true,this.fromCheckOut=false}) : super(key: key);
|
||||
|
||||
@override
|
||||
State<Orders> createState() => _OrdersState();
|
||||
}
|
||||
|
||||
class _OrdersState extends State<Orders> {
|
||||
OrderPresenter order = OrderPresenter();
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
Provider.of<OrderPresenter>(context, listen: false).setContext(context);
|
||||
WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
|
||||
Provider.of<OrderPresenter>(context, listen: false).initState();
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return PopScope(
|
||||
onPopInvoked: (a) async {
|
||||
if(widget.fromCheckOut){
|
||||
MakeRoute.goAndRemoveAll(context, const Main());
|
||||
return Future(() => true);
|
||||
}
|
||||
return Future(() => true);
|
||||
},
|
||||
child: Scaffold(
|
||||
backgroundColor: ThemeConfig.xxlightGrey,
|
||||
appBar: CommonAppbar.show(
|
||||
title: AppLang.local(context).orders,
|
||||
context: context,
|
||||
gotoMain: widget.fromCheckOut,
|
||||
showBackButton: !widget.fromBottomBar),
|
||||
body: Consumer<OrderPresenter>(builder: (context, data, child) {
|
||||
return RefreshIndicator(
|
||||
onRefresh: () => data.onRefresh(),
|
||||
child: SingleChildScrollView(
|
||||
child: Column(
|
||||
children: [
|
||||
const SizedBox(
|
||||
height: 10,
|
||||
),
|
||||
buildTapbar(context, data),
|
||||
if (!data.isOrdersInit)
|
||||
SizedBox(
|
||||
width: getWidth(context),
|
||||
height: getHeight(context) - 100,
|
||||
child: Shimmers.list(10, getWidth(context), 80),
|
||||
)
|
||||
else if (data.isOrdersInit && data.orders.isNotEmpty)
|
||||
ListView.separated(
|
||||
padding: EdgeInsets.only(
|
||||
left: 10,
|
||||
right: 10,
|
||||
top: 10,
|
||||
bottom: widget.fromBottomBar ? 80 : 10),
|
||||
scrollDirection: Axis.vertical,
|
||||
physics: const NeverScrollableScrollPhysics(),
|
||||
shrinkWrap: true,
|
||||
itemCount: data.orders.length,
|
||||
separatorBuilder: (context, index) {
|
||||
return const SizedBox(
|
||||
height: 10,
|
||||
);
|
||||
},
|
||||
itemBuilder: (context, index) {
|
||||
return Button(
|
||||
//padding: EdgeInsets.symmetric(vertical: 10,horizontal: 20),
|
||||
minWidth: 100,
|
||||
onPressed: () {},
|
||||
child: OrderViewModel(
|
||||
orderInfo: data.orders[index],
|
||||
context: context,
|
||||
));
|
||||
},
|
||||
)
|
||||
else
|
||||
Container(
|
||||
height: getHeight(context)-180,
|
||||
alignment: Alignment.center,
|
||||
child: Text(AppLang.local(context).data_is_not_available))
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
SizedBox buildTapbar(BuildContext context, OrderPresenter data) {
|
||||
return SizedBox(
|
||||
// color: Colors.red,
|
||||
width: getWidth(context),
|
||||
height: 40,
|
||||
child: ListView.separated(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 10),
|
||||
scrollDirection: Axis.horizontal,
|
||||
itemCount: data.searchKey.values.length,
|
||||
separatorBuilder: (context, index) {
|
||||
return const SizedBox(
|
||||
width: 10,
|
||||
);
|
||||
},
|
||||
itemBuilder: (context, index) {
|
||||
return Button(
|
||||
padding: const EdgeInsets.symmetric(vertical: 3, horizontal: 15),
|
||||
color: data.keySelectedIndex == index
|
||||
? ThemeConfig.red
|
||||
: ThemeConfig.white,
|
||||
minWidth: 80,
|
||||
minHeight: 40.0,
|
||||
shape: StyleConfig.buttonRadius(10),
|
||||
onPressed: () {
|
||||
data.onChangeIndex(index);
|
||||
},
|
||||
child: Text( data.searchKey.values.elementAt(index),
|
||||
style: data.keySelectedIndex == index
|
||||
? StyleConfig.fs14cWhitefwBold
|
||||
: StyleConfig.fs14fwBold,
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
27
app_code/lib/screens/order/pdf_api.dart
Normal file
27
app_code/lib/screens/order/pdf_api.dart
Normal file
@@ -0,0 +1,27 @@
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:open_file/open_file.dart';
|
||||
import 'package:path_provider/path_provider.dart';
|
||||
import 'package:pdf/widgets.dart';
|
||||
|
||||
class PdfApi {
|
||||
static Future<File> saveDocument({
|
||||
required String name,
|
||||
required Document pdf,
|
||||
}) async {
|
||||
final bytes = await pdf.save();
|
||||
|
||||
final dir = await getApplicationDocumentsDirectory();
|
||||
final file = File('${dir.path}/$name');
|
||||
|
||||
await file.writeAsBytes(bytes);
|
||||
|
||||
return file;
|
||||
}
|
||||
|
||||
static Future openFile(File file) async {
|
||||
final url = file.path;
|
||||
|
||||
await OpenFile.open(url);
|
||||
}
|
||||
}
|
||||
152
app_code/lib/screens/order/pdf_invoice_api.dart
Normal file
152
app_code/lib/screens/order/pdf_invoice_api.dart
Normal file
@@ -0,0 +1,152 @@
|
||||
import 'dart:io';
|
||||
import 'package:flutter/material.dart' show Colors;
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:grostore/helpers/common_functions.dart';
|
||||
import 'package:grostore/screens/order/pdf_api.dart';
|
||||
import 'package:pdf/pdf.dart';
|
||||
import 'package:pdf/widgets.dart' as pw;
|
||||
import 'package:pdf/widgets.dart';
|
||||
|
||||
import '../../models/order/order_details_response.dart';
|
||||
|
||||
class PdfInvoiceApi {
|
||||
static Future<File> generate(OrderDetailsInfo? detailsInfo) async {
|
||||
final img = await rootBundle.load(getAssetLogo("logo2x2.png"));
|
||||
final imageBytes = img.buffer.asUint8List();
|
||||
|
||||
final imgQr = await rootBundle.load(getAssetLogo("img.png"));
|
||||
final qr = imgQr.buffer.asUint8List();
|
||||
final pdf = Document();
|
||||
|
||||
pdf.addPage(MultiPage(
|
||||
build: (context) => [
|
||||
buildLogo(imageBytes),
|
||||
pw.SizedBox(height: 0.3 * PdfPageFormat.cm),
|
||||
buildDottedDivider(),
|
||||
pw.SizedBox(height: 0.5 * PdfPageFormat.cm),
|
||||
buildAddress(
|
||||
"${detailsInfo?.shippingAddress?.address}, ${detailsInfo?.shippingAddress?.cityName}, ${detailsInfo?.shippingAddress?.stateName}, ${detailsInfo?.shippingAddress?.countryName}"),
|
||||
pw.SizedBox(height: 0.3 * PdfPageFormat.cm),
|
||||
buildPhoneNumber("${detailsInfo?.payment_method}"),
|
||||
pw.SizedBox(height: 0.5 * PdfPageFormat.cm),
|
||||
buildDottedDivider(),
|
||||
pw.SizedBox(height: 0.5 * PdfPageFormat.cm),
|
||||
buildCheckDate("${detailsInfo?.code}", "${detailsInfo?.date}"),
|
||||
pw.SizedBox(height: 0.3 * PdfPageFormat.cm),
|
||||
buildDottedDivider(),
|
||||
pw.SizedBox(height: 0.5 * PdfPageFormat.cm),
|
||||
buildItemsList(detailsInfo?.items ?? []),
|
||||
pw.SizedBox(height: 0.7 * PdfPageFormat.cm),
|
||||
buildDottedDivider(),
|
||||
pw.SizedBox(height: 0.5 * PdfPageFormat.cm),
|
||||
buildSummery(detailsInfo),
|
||||
buildDottedDivider(),
|
||||
pw.SizedBox(height: 1.2 * PdfPageFormat.cm),
|
||||
buildQrCode(qr)
|
||||
],
|
||||
//footer: (context) => buildFooter(invoice),
|
||||
));
|
||||
|
||||
return PdfApi.saveDocument(name: 'Check.pdf', pdf: pdf);
|
||||
}
|
||||
|
||||
static Widget buildLogo(Uint8List image) {
|
||||
return Row(mainAxisAlignment: pw.MainAxisAlignment.spaceBetween, children: [
|
||||
Text("Karvon market",
|
||||
style: TextStyle(
|
||||
fontSize: 20,
|
||||
fontWeight: FontWeight.bold,
|
||||
)),
|
||||
pw.Image(pw.MemoryImage(image), height: 40)
|
||||
]);
|
||||
}
|
||||
|
||||
static Widget buildDottedDivider() {
|
||||
return Row(
|
||||
children: List.generate(
|
||||
800 ~/ 10,
|
||||
(index) => index % 2 == 0
|
||||
? Expanded(
|
||||
child: pw.Container(height: 1, color: PdfColor(0, 0, 0)),
|
||||
)
|
||||
: Expanded(
|
||||
child: Container(height: 2, color: null),
|
||||
)));
|
||||
}
|
||||
|
||||
static Widget buildAddress(String address) {
|
||||
return pw.Text(address, style: TextStyle(fontSize: 14));
|
||||
}
|
||||
|
||||
static Widget buildPhoneNumber(String phoneNumber) {
|
||||
return pw.Text("To'lov turi: $phoneNumber", style: TextStyle(fontSize: 14));
|
||||
}
|
||||
|
||||
static Widget buildCheckDate(String checkNumber, String date) {
|
||||
return Column(
|
||||
mainAxisAlignment: pw.MainAxisAlignment.start,
|
||||
crossAxisAlignment: pw.CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text("Check raqami: $checkNumber", style: TextStyle(fontSize: 14)),
|
||||
pw.SizedBox(height: 0.2 * PdfPageFormat.cm),
|
||||
Text("Chiqarilgan: $date", style: TextStyle(fontSize: 14))
|
||||
]);
|
||||
}
|
||||
|
||||
static Widget buildItemsList(List<Item> items) {
|
||||
return Column(
|
||||
mainAxisSize: pw.MainAxisSize.min,
|
||||
mainAxisAlignment: pw.MainAxisAlignment.start,
|
||||
children: List.generate(
|
||||
items.length,
|
||||
(index) => Column(
|
||||
crossAxisAlignment: pw.CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text("${index + 1}.${items[index].product?.name}",
|
||||
style: TextStyle(
|
||||
fontSize: 16, fontWeight: pw.FontWeight.bold)),
|
||||
pw.SizedBox(height: 0.1 * PdfPageFormat.cm),
|
||||
Row(
|
||||
mainAxisAlignment: pw.MainAxisAlignment.spaceAround,
|
||||
children: [
|
||||
Text("Narxi:",
|
||||
style: TextStyle(
|
||||
fontSize: 16, fontWeight: pw.FontWeight.normal)),
|
||||
Text(items[index].unitPrice,
|
||||
style: TextStyle(
|
||||
fontSize: 15, fontWeight: pw.FontWeight.normal)),
|
||||
Text("${items[index].qty} ta",
|
||||
style: TextStyle(
|
||||
fontSize: 15, fontWeight: pw.FontWeight.normal)),
|
||||
Text(items[index].totalPrice,
|
||||
style: TextStyle(
|
||||
fontSize: 17, fontWeight: pw.FontWeight.bold)),
|
||||
])
|
||||
]),
|
||||
));
|
||||
}
|
||||
|
||||
static Widget buildSummery(OrderDetailsInfo? info) {
|
||||
return Column(
|
||||
crossAxisAlignment: pw.CrossAxisAlignment.start,
|
||||
mainAxisAlignment: pw.MainAxisAlignment.start,
|
||||
children: [
|
||||
Text("Mahsulot narxi: ${info?.subTotalAmount}",
|
||||
style: TextStyle(fontSize: 15)),
|
||||
pw.SizedBox(height: 0.2 * PdfPageFormat.cm),
|
||||
Text("Yuk tashish narxi:${info?.totalShippingCost}",
|
||||
style: TextStyle(fontSize: 15)),
|
||||
pw.SizedBox(height: 0.2 * PdfPageFormat.cm),
|
||||
Text("Chegirmasi: ${info?.couponDiscountAmount}",
|
||||
style: TextStyle(fontSize: 15)),
|
||||
pw.SizedBox(height: 0.2 * PdfPageFormat.cm),
|
||||
Text("Jami narxi: ${info?.totalPrice}",
|
||||
style: TextStyle(fontSize: 15, fontWeight: pw.FontWeight.bold)),
|
||||
pw.SizedBox(height: 0.5 * PdfPageFormat.cm),
|
||||
]);
|
||||
}
|
||||
|
||||
static Widget buildQrCode(Uint8List qrcode) {
|
||||
return pw.Center(child: pw.Image(pw.MemoryImage(qrcode), height: 200));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user