apskel-pos-flutter/lib/presentation/home/widgets/success_payment_dialog.dart
2025-08-06 18:47:20 +07:00

350 lines
14 KiB
Dart

// ignore_for_file: public_member_api_docs, sort_constructors_first
import 'dart:developer';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:intl/intl.dart';
import 'package:enaklo_pos/core/extensions/build_context_ext.dart';
import 'package:enaklo_pos/core/extensions/int_ext.dart';
import 'package:enaklo_pos/core/extensions/string_ext.dart';
import 'package:enaklo_pos/data/dataoutputs/print_dataoutputs.dart';
import 'package:enaklo_pos/data/datasources/product_local_datasource.dart';
import 'package:enaklo_pos/presentation/home/models/product_quantity.dart';
import 'package:enaklo_pos/presentation/home/models/order_type.dart';
import 'package:enaklo_pos/core/utils/printer_service.dart';
import 'package:enaklo_pos/data/datasources/settings_local_datasource.dart';
import '../../../core/assets/assets.gen.dart';
import '../../../core/components/buttons.dart';
import '../../../core/components/spaces.dart';
import '../../table/blocs/get_table/get_table_bloc.dart';
import '../bloc/checkout/checkout_bloc.dart';
import '../bloc/order/order_bloc.dart';
class SuccessPaymentDialog extends StatefulWidget {
const SuccessPaymentDialog({
Key? key,
required this.data,
required this.totalQty,
required this.totalPrice,
required this.totalTax,
required this.totalDiscount,
required this.subTotal,
required this.normalPrice,
required this.totalService,
required this.draftName,
this.isTablePaymentPage = false,
}) : super(key: key);
final List<ProductQuantity> data;
final int totalQty;
final int totalPrice;
final int totalTax;
final int totalDiscount;
final int subTotal;
final int normalPrice;
final int totalService;
final String draftName;
final bool? isTablePaymentPage;
@override
State<SuccessPaymentDialog> createState() => _SuccessPaymentDialogState();
}
class _SuccessPaymentDialogState extends State<SuccessPaymentDialog> {
// List<ProductQuantity> data = [];
// int totalQty = 0;
// int totalPrice = 0;
@override
Widget build(BuildContext context) {
return AlertDialog(
content: SingleChildScrollView(
padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 20),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Center(child: Assets.icons.success.svg()),
const SpaceHeight(16.0),
const Center(
child: Text(
'Pembayaran telah sukses dilakukan',
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 20,
),
),
),
const SpaceHeight(20.0),
const Text('METODE BAYAR'),
const SpaceHeight(5.0),
BlocBuilder<OrderBloc, OrderState>(
builder: (context, state) {
final paymentMethod = state.maybeWhen(
orElse: () => 'Cash',
loaded: (model, orderId) => model.paymentMethod,
);
return Text(
paymentMethod,
style: const TextStyle(
fontWeight: FontWeight.w700,
),
);
},
),
const SpaceHeight(10.0),
const Divider(),
const SpaceHeight(8.0),
const Text('TOTAL TAGIHAN'),
const SpaceHeight(5.0),
BlocBuilder<OrderBloc, OrderState>(
builder: (context, state) {
state.maybeWhen(
orElse: () => 0,
loaded: (model, orderId) => model.total,
);
return Text(
widget.totalPrice.currencyFormatRp,
style: const TextStyle(
fontWeight: FontWeight.w700,
),
);
},
),
const SpaceHeight(10.0),
const Divider(),
const SpaceHeight(8.0),
const Text('NOMINAL BAYAR'),
const SpaceHeight(5.0),
BlocBuilder<OrderBloc, OrderState>(
builder: (context, state) {
final paymentAmount = state.maybeWhen(
orElse: () => 0,
loaded: (model, orderId) => model.paymentAmount,
);
return Text(
paymentAmount.ceil().currencyFormatRp,
style: const TextStyle(
fontWeight: FontWeight.w700,
),
);
},
),
const Divider(),
const SpaceHeight(8.0),
const Text('KEMBALIAN'),
const SpaceHeight(5.0),
BlocBuilder<OrderBloc, OrderState>(
builder: (context, state) {
final paymentAmount = state.maybeWhen(
orElse: () => 0,
loaded: (model, orderId) => model.paymentAmount,
);
final total = state.maybeWhen(
orElse: () => 0,
loaded: (model, orderId) => model.total,
);
final diff = paymentAmount - total;
log("DIFF: $diff paymentAmount: $paymentAmount total: $total");
return Text(
diff.ceil().currencyFormatRp,
style: const TextStyle(
fontWeight: FontWeight.w700,
),
);
},
),
const SpaceHeight(10.0),
const Divider(),
const SpaceHeight(8.0),
const Text('WAKTU PEMBAYARAN'),
const SpaceHeight(5.0),
Text(
DateFormat('dd MMMM yyyy, HH:mm').format(DateTime.now()),
style: const TextStyle(
fontWeight: FontWeight.w700,
),
),
const SpaceHeight(20.0),
Row(
children: [
Flexible(
child: Button.outlined(
onPressed: () {
// For table payment page, just close the dialog
// The cleanup and navigation is handled by the payment page
if (widget.isTablePaymentPage == true) {
Navigator.of(context).pop(); // Close dialog only
} else {
// For regular payment flow, reset and go to root
context
.read<CheckoutBloc>()
.add(const CheckoutEvent.started());
context
.read<GetTableBloc>()
.add(const GetTableEvent.getTables());
context.popToRoot();
}
},
label: 'Kembali',
),
),
const SpaceWidth(8.0),
Flexible(
child: BlocBuilder<OrderBloc, OrderState>(
builder: (context, state) {
final paymentAmount = state.maybeWhen(
orElse: () => 0,
loaded: (model, orderId) => model.paymentAmount,
);
final kembalian = paymentAmount - widget.totalPrice;
return BlocBuilder<CheckoutBloc, CheckoutState>(
builder: (context, checkoutState) {
final orderType = checkoutState.maybeWhen(
orElse: () => OrderType.dineIn,
loaded: (
items,
discountModel,
discount,
discountAmount,
tax,
serviceCharge,
totalQuantity,
totalPrice,
draftName,
orderType,
deliveryType,
) =>
orderType,
);
return Button.filled(
onPressed: () async {
final receiptPrinter =
await ProductLocalDatasource.instance
.getPrinterByCode('receipt');
final kitchenPrinter =
await ProductLocalDatasource.instance
.getPrinterByCode('kitchen');
final barPrinter = await ProductLocalDatasource
.instance
.getPrinterByCode('bar');
// Receipt Printer
if (receiptPrinter != null) {
try {
final settingsLocalDatasource =
SettingsLocalDatasource();
final taxModel =
await settingsLocalDatasource.getTax();
final serviceChargeValue =
await settingsLocalDatasource
.getServiceCharge();
// Get the actual payment method from OrderBloc
final paymentMethod = state.maybeWhen(
orElse: () => 'Cash',
loaded: (model, orderId) =>
model.paymentMethod,
);
final printValue = await PrintDataoutputs
.instance
.printOrderV3(
widget.data,
widget.totalQty,
widget.totalPrice,
paymentMethod,
paymentAmount,
kembalian,
widget.subTotal,
widget.totalDiscount,
widget.totalTax,
widget.totalService,
'kasir',
widget.draftName,
receiptPrinter.paper.toIntegerFromText,
taxPercentage: taxModel.value,
serviceChargePercentage: serviceChargeValue,
);
await PrinterService().printWithPrinter(
receiptPrinter, printValue, context);
} catch (e) {
log("Error printing receipt: $e");
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content:
Text('Error printing receipt: $e')),
);
}
}
// Kitchen Printer
if (kitchenPrinter != null &&
widget.isTablePaymentPage == false) {
try {
final printValue = await PrintDataoutputs
.instance
.printKitchen(
widget.data,
'',
widget.draftName,
'kasir',
kitchenPrinter.paper.toIntegerFromText,
orderType.value,
);
await PrinterService().printWithPrinter(
kitchenPrinter, printValue, context);
} catch (e) {
log("Error printing kitchen order: $e");
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text(
'Error printing kitchen order: $e')),
);
}
}
// Bar printer
if (barPrinter != null &&
widget.isTablePaymentPage == false) {
try {
final printValue =
await PrintDataoutputs.instance.printBar(
widget.data,
'',
widget.draftName,
'kasir',
barPrinter.paper.toIntegerFromText,
orderType.value,
);
await PrinterService().printWithPrinter(
barPrinter, printValue, context);
} catch (e) {
log("Error printing bar order: $e");
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text(
'Error printing bar order: $e')),
);
}
}
},
label: 'Print',
);
},
);
},
),
),
],
),
],
),
),
);
}
}