POS Grosir Dutra Store: update kasir/produk/riwayat/pengaturan + offline queue
This commit is contained in:
@@ -512,66 +512,71 @@ class _RiwayatScreenState extends State<RiwayatScreen> {
|
||||
BuildContext parentContext, BuildContext sheetContext, Sale sale, ScrollController controller) {
|
||||
final state = parentContext.read<AppState>();
|
||||
final isAdmin = state.isAdmin;
|
||||
final isCancelled = sale.isCancelled;
|
||||
final isKasir = state.isKasir;
|
||||
|
||||
return Container(
|
||||
decoration: const BoxDecoration(
|
||||
color: kSurface,
|
||||
borderRadius: BorderRadius.vertical(top: Radius.circular(24)),
|
||||
border: Border(top: BorderSide(color: kBorder)),
|
||||
),
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Container(
|
||||
margin: const EdgeInsets.only(top: 12),
|
||||
width: 40,
|
||||
height: 4,
|
||||
decoration: BoxDecoration(
|
||||
color: kBorder,
|
||||
borderRadius: BorderRadius.circular(4),
|
||||
),
|
||||
return StatefulBuilder(
|
||||
builder: (context, setSheet) {
|
||||
Sale currentSale = sale;
|
||||
final isCancelled = currentSale.isCancelled;
|
||||
|
||||
return Container(
|
||||
decoration: const BoxDecoration(
|
||||
color: kSurface,
|
||||
borderRadius: BorderRadius.vertical(top: Radius.circular(24)),
|
||||
border: Border(top: BorderSide(color: kBorder)),
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.fromLTRB(16, 12, 16, 4),
|
||||
child: Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text('#${sale.id.toUpperCase()}',
|
||||
style: const TextStyle(fontSize: 10, color: kMuted),
|
||||
overflow: TextOverflow.ellipsis),
|
||||
Text(
|
||||
'Kasir: ${state.getProfileName(sale.userId)}',
|
||||
style: const TextStyle(color: kMuted, fontSize: 11),
|
||||
),
|
||||
],
|
||||
),
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Container(
|
||||
margin: const EdgeInsets.only(top: 12),
|
||||
width: 40,
|
||||
height: 4,
|
||||
decoration: BoxDecoration(
|
||||
color: kBorder,
|
||||
borderRadius: BorderRadius.circular(4),
|
||||
),
|
||||
if (isCancelled)
|
||||
Container(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: 8, vertical: 2),
|
||||
decoration: BoxDecoration(
|
||||
color: kDanger.withValues(alpha: 0.15),
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.fromLTRB(16, 12, 16, 4),
|
||||
child: Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text('#${currentSale.id.toUpperCase()}',
|
||||
style: const TextStyle(fontSize: 10, color: kMuted),
|
||||
overflow: TextOverflow.ellipsis),
|
||||
Text(
|
||||
'Kasir: ${state.getProfileName(currentSale.userId)}',
|
||||
style: const TextStyle(color: kMuted, fontSize: 11),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
child: const Text(
|
||||
'DIBATALKAN',
|
||||
style: TextStyle(
|
||||
fontSize: 10,
|
||||
fontWeight: FontWeight.w700,
|
||||
color: kDanger),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
if (isCancelled)
|
||||
Container(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: 8, vertical: 2),
|
||||
decoration: BoxDecoration(
|
||||
color: kDanger.withValues(alpha: 0.15),
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
),
|
||||
child: const Text(
|
||||
'DIBATALKAN',
|
||||
style: TextStyle(
|
||||
fontSize: 10,
|
||||
fontWeight: FontWeight.w700,
|
||||
color: kDanger),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 2),
|
||||
Text(
|
||||
'${formatTanggal(sale.date)} ${formatWaktu(sale.date)}',
|
||||
'${formatTanggal(currentSale.date)} ${formatWaktu(currentSale.date)}',
|
||||
style: const TextStyle(color: kMuted, fontSize: 12),
|
||||
),
|
||||
const Divider(height: 24),
|
||||
@@ -582,14 +587,21 @@ class _RiwayatScreenState extends State<RiwayatScreen> {
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
...sale.items.map((it) => Padding(
|
||||
...currentSale.items.map((it) => Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 4),
|
||||
child: Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Expanded(
|
||||
child: Text('${it.name} x${it.qty}',
|
||||
style: const TextStyle(fontSize: 14)),
|
||||
child: Text(
|
||||
it.productId.startsWith('manual-')
|
||||
? '[MANUAL] ${it.name} x${it.qty}'
|
||||
: '${it.name} x${it.qty}',
|
||||
style: TextStyle(
|
||||
fontSize: 14,
|
||||
color: it.productId.startsWith('manual-') ? kAccent : null,
|
||||
),
|
||||
),
|
||||
),
|
||||
Text(formatRupiah(it.subtotal),
|
||||
style: const TextStyle(
|
||||
@@ -597,40 +609,41 @@ class _RiwayatScreenState extends State<RiwayatScreen> {
|
||||
],
|
||||
),
|
||||
)),
|
||||
if (sale.discount > 0)
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 4),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
const Text('Diskon', style: TextStyle(color: kMuted)),
|
||||
Text('-${formatRupiah(sale.discount)}',
|
||||
style: const TextStyle(color: kMuted)),
|
||||
],
|
||||
),
|
||||
),
|
||||
const Divider(height: 24),
|
||||
_receiptRow('Total', formatRupiah(sale.total), true),
|
||||
_receiptRow('Bayar', formatRupiah(sale.paid), false),
|
||||
if (sale.paymentStatus == 'unpaid' || sale.paymentStatus == 'partial')
|
||||
_receiptRow('Sisa', formatRupiah(sale.dueAmount), false),
|
||||
_receiptRow('Kembali', formatRupiah(sale.change), false),
|
||||
_receiptRow('Metode', _paymentMethodLabel(sale.paymentMethod), false),
|
||||
_receiptRow('Status', sale.paymentStatus == 'paid' ? 'Lunas' : 'Belum Lunas', false),
|
||||
if (sale.splitPayment != null && sale.splitPayment!.isNotEmpty)
|
||||
...sale.splitPayment!.entries.map((e) {
|
||||
final label = e.key == 'tunai'
|
||||
? 'Tunai'
|
||||
: e.key == 'transfer'
|
||||
? 'Bank'
|
||||
: 'QRIS';
|
||||
return _receiptRow('Split $label', formatRupiah(e.value), false);
|
||||
}),
|
||||
if (sale.totalCost > 0) ...[
|
||||
const Divider(height: 24),
|
||||
_receiptRow('Harga Pokok', formatRupiah(sale.totalCost), false),
|
||||
_receiptRow('Laba Kotor', formatRupiah(sale.total - sale.totalCost), true),
|
||||
],
|
||||
if (currentSale.discount > 0)
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 4),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
const Text('Diskon', style: TextStyle(color: kMuted)),
|
||||
Text('-${formatRupiah(currentSale.discount)}',
|
||||
style: const TextStyle(color: kMuted)),
|
||||
],
|
||||
),
|
||||
),
|
||||
const Divider(height: 24),
|
||||
_receiptRow('Total', formatRupiah(currentSale.total), true),
|
||||
_receiptRow('Bayar', formatRupiah(currentSale.paid), false),
|
||||
if (currentSale.paymentStatus == 'unpaid' || currentSale.paymentStatus == 'partial')
|
||||
_receiptRow('Sisa', formatRupiah(currentSale.dueAmount), false),
|
||||
if (currentSale.paymentStatus == 'paid')
|
||||
_receiptRow('Kembali', formatRupiah(currentSale.change.clamp(0, double.infinity)), false),
|
||||
_receiptRow('Metode', _paymentMethodLabel(currentSale.paymentMethod), false),
|
||||
_receiptRow('Status', currentSale.paymentStatus == 'paid' ? 'Lunas' : 'Belum Lunas', false),
|
||||
if (currentSale.splitPayment != null && currentSale.splitPayment!.isNotEmpty)
|
||||
...currentSale.splitPayment!.entries.map((e) {
|
||||
final label = e.key == 'tunai'
|
||||
? 'Tunai'
|
||||
: e.key == 'transfer'
|
||||
? 'Bank'
|
||||
: 'QRIS';
|
||||
return _receiptRow('Split $label', formatRupiah(e.value), false);
|
||||
}),
|
||||
if (!state.isKasir && currentSale.totalCost > 0) ...[
|
||||
const Divider(height: 24),
|
||||
_receiptRow('Harga Pokok', formatRupiah(currentSale.totalCost), false),
|
||||
_receiptRow('Laba Kotor', formatRupiah(currentSale.total - currentSale.totalCost), true),
|
||||
],
|
||||
const SizedBox(height: 16),
|
||||
SizedBox(
|
||||
width: double.infinity,
|
||||
@@ -644,9 +657,9 @@ class _RiwayatScreenState extends State<RiwayatScreen> {
|
||||
prefs.getString('store_name') ?? 'Toko Grosir';
|
||||
final err =
|
||||
await printerService.printSale(
|
||||
sale,
|
||||
currentSale,
|
||||
storeName,
|
||||
kasirName: state.getProfileName(sale.userId),
|
||||
kasirName: state.getProfileName(currentSale.userId),
|
||||
whatsapp: prefs.getString('store_whatsapp'),
|
||||
notes: prefs.getString('store_notes'),
|
||||
);
|
||||
@@ -665,7 +678,7 @@ class _RiwayatScreenState extends State<RiwayatScreen> {
|
||||
label: const Text('Cetak Struk'),
|
||||
),
|
||||
),
|
||||
if (isAdmin && !isCancelled && sale.paymentStatus != 'paid') ...[
|
||||
if ((isAdmin || isKasir) && !isCancelled && currentSale.paymentStatus != 'paid') ...[
|
||||
const SizedBox(height: 4),
|
||||
SizedBox(
|
||||
width: double.infinity,
|
||||
@@ -674,60 +687,168 @@ class _RiwayatScreenState extends State<RiwayatScreen> {
|
||||
final payCtrl = TextEditingController();
|
||||
final result = await showDialog<double>(
|
||||
context: parentContext,
|
||||
builder: (ctx) => AlertDialog(
|
||||
title: Text(sale.paymentStatus == 'unpaid' ? 'Terima Pembayaran' : 'Bayar Sisa'),
|
||||
content: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text('Total: ${formatRupiah(sale.total)}'),
|
||||
Text('Sudah bayar: ${formatRupiah(sale.paid)}'),
|
||||
Text('Sisa: ${formatRupiah(sale.dueAmount)}'),
|
||||
const SizedBox(height: 12),
|
||||
TextField(
|
||||
controller: payCtrl,
|
||||
keyboardType: TextInputType.number,
|
||||
inputFormatters: [RupiahInputFormatter()],
|
||||
decoration: const InputDecoration(
|
||||
labelText: 'Nominal Pembayaran',
|
||||
prefixText: 'Rp ',
|
||||
builder: (ctx) {
|
||||
bool submitting = false;
|
||||
return StatefulBuilder(
|
||||
builder: (context, setDialog) {
|
||||
final isUnpaid = currentSale.paymentStatus == 'unpaid';
|
||||
final remain = currentSale.dueAmount - currentSale.paid;
|
||||
final remainColor = remain <= 0 ? kSuccess : kDanger;
|
||||
return AlertDialog(
|
||||
title: Text(isUnpaid ? 'Terima Pembayaran' : 'Bayar Sisa'),
|
||||
content: SingleChildScrollView(
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Container(
|
||||
width: double.infinity,
|
||||
padding: const EdgeInsets.all(14),
|
||||
decoration: BoxDecoration(
|
||||
color: kSurface2,
|
||||
borderRadius: BorderRadius.circular(14),
|
||||
),
|
||||
child: Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
const Text('Total', style: TextStyle(color: kMuted, fontSize: 12)),
|
||||
Text(formatRupiah(currentSale.total),
|
||||
style: const TextStyle(fontSize: 15, fontWeight: FontWeight.w700)),
|
||||
],
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
const Text('Sudah Bayar', style: TextStyle(color: kMuted, fontSize: 12)),
|
||||
Text(formatRupiah(currentSale.paid),
|
||||
style: const TextStyle(fontSize: 15, fontWeight: FontWeight.w700)),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
Container(
|
||||
width: double.infinity,
|
||||
padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 10),
|
||||
decoration: BoxDecoration(
|
||||
color: remainColor.withValues(alpha: 0.12),
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Text(isUnpaid ? 'Sisa Tagihan' : 'Sisa',
|
||||
style: TextStyle(color: remainColor, fontSize: 13, fontWeight: FontWeight.w600)),
|
||||
Text(formatRupiah(remain > 0 ? remain : 0),
|
||||
style: TextStyle(color: remainColor, fontSize: 16, fontWeight: FontWeight.w800)),
|
||||
],
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
Container(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 6),
|
||||
decoration: BoxDecoration(
|
||||
color: isUnpaid ? kMuted.withValues(alpha: 0.12) : kAccent.withValues(alpha: 0.12),
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
),
|
||||
child: Text(isUnpaid ? 'Transaksi belum lunas' : 'Pembayaran sebagian',
|
||||
style: TextStyle(color: isUnpaid ? kMuted : kAccent, fontSize: 12, fontWeight: FontWeight.w600)),
|
||||
),
|
||||
const SizedBox(height: 14),
|
||||
TextField(
|
||||
controller: payCtrl,
|
||||
keyboardType: TextInputType.number,
|
||||
inputFormatters: [RupiahInputFormatter()],
|
||||
decoration: InputDecoration(
|
||||
labelText: 'Nominal Pembayaran',
|
||||
prefixText: 'Rp ',
|
||||
helperText: isUnpaid ? 'Masukkan nominal sesuai yang dibayar customer' : 'Masukkan jumlah pelunasan',
|
||||
helperStyle: TextStyle(color: kMuted, fontSize: 12),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
actions: [
|
||||
TextButton(onPressed: () => Navigator.pop(ctx), child: const Text('Batal')),
|
||||
FilledButton(
|
||||
onPressed: () {
|
||||
final val = (RupiahInputFormatter.getRawValue(payCtrl.text) ?? 0).toDouble();
|
||||
if (val <= 0) return;
|
||||
Navigator.pop(ctx, val);
|
||||
},
|
||||
style: FilledButton.styleFrom(backgroundColor: kSuccess),
|
||||
child: const Text('Simpan'),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
if (result != null && result > 0) {
|
||||
final err = await state.recordPayment(sale.id, result);
|
||||
if (mounted) {
|
||||
final messenger = ScaffoldMessenger.of(parentContext);
|
||||
messenger.showSnackBar(
|
||||
SnackBar(
|
||||
content: Text(err == null ? 'Pembayaran berhasil dicatat' : 'Gagal: $err'),
|
||||
backgroundColor: err == null ? kSuccess : kDanger,
|
||||
),
|
||||
actions: [
|
||||
Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: OutlinedButton(
|
||||
onPressed: submitting ? null : () => Navigator.pop(ctx),
|
||||
style: OutlinedButton.styleFrom(
|
||||
foregroundColor: kMuted,
|
||||
side: const BorderSide(color: kBorder),
|
||||
),
|
||||
child: const Text('Batal'),
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 10),
|
||||
Expanded(
|
||||
child: FilledButton(
|
||||
onPressed: submitting
|
||||
? null
|
||||
: () {
|
||||
final val = (RupiahInputFormatter.getRawValue(payCtrl.text) ?? 0).toDouble();
|
||||
if (val <= 0) return;
|
||||
Navigator.pop(ctx, val);
|
||||
},
|
||||
style: FilledButton.styleFrom(backgroundColor: kSuccess, foregroundColor: const Color(0xFF06210F)),
|
||||
child: submitting
|
||||
? const SizedBox(height: 18, width: 18, child: CircularProgressIndicator(strokeWidth: 2, color: Color(0xFF06210F)))
|
||||
: const Text('Simpan'),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
);
|
||||
},
|
||||
);
|
||||
if (result != null && result > 0) {
|
||||
final err = await state.recordPayment(currentSale.id, result);
|
||||
Sale? updated;
|
||||
try {
|
||||
updated = state.sales.firstWhere((s) => s.id == currentSale.id);
|
||||
} catch (_) {}
|
||||
final isNowPaid = updated?.paymentStatus == 'paid';
|
||||
final remainAfter = isNowPaid
|
||||
? 0.0
|
||||
: (updated?.dueAmount ?? (currentSale.dueAmount - result)).clamp(0, double.infinity);
|
||||
|
||||
if (sheetContext.mounted) {
|
||||
Navigator.pop(sheetContext);
|
||||
}
|
||||
if (mounted) {
|
||||
final messenger = ScaffoldMessenger.of(parentContext);
|
||||
final msg = err == null
|
||||
? isNowPaid
|
||||
? 'Pembayaran lunas dicatat'
|
||||
: 'Pembayaran ${formatRupiah(result.toDouble())} dicatat. Sisa: ${formatRupiah(remainAfter.toDouble())}'
|
||||
: 'Gagal: $err';
|
||||
messenger.showSnackBar(
|
||||
SnackBar(
|
||||
content: Text(msg),
|
||||
backgroundColor: err == null ? kSuccess : kDanger,
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
icon: const Icon(Icons.payments_outlined, color: Colors.white),
|
||||
label: Text(sale.paymentStatus == 'unpaid' ? 'Terima Pembayaran' : 'Bayar Sisa'),
|
||||
style: FilledButton.styleFrom(
|
||||
backgroundColor: kSuccess,
|
||||
foregroundColor: const Color(0xFF06210F),
|
||||
),
|
||||
icon: const Icon(Icons.payments_outlined, color: Colors.white),
|
||||
label: Text(currentSale.paymentStatus == 'unpaid' ? 'Terima Pembayaran' : 'Bayar Sisa'),
|
||||
style: FilledButton.styleFrom(
|
||||
backgroundColor: kSuccess,
|
||||
foregroundColor: const Color(0xFF06210F),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
@@ -740,40 +861,51 @@ class _RiwayatScreenState extends State<RiwayatScreen> {
|
||||
final messenger = ScaffoldMessenger.of(parentContext);
|
||||
final confirm = await showDialog<bool>(
|
||||
context: parentContext,
|
||||
builder: (ctx) => AlertDialog(
|
||||
icon: Icon(Icons.cancel_outlined, color: kDanger, size: 28),
|
||||
title: const Text('Batalkan Transaksi?'),
|
||||
content: const Text(
|
||||
'Stok akan dikembalikan secara otomatis. Tindakan ini tidak dapat dibatalkan.',
|
||||
),
|
||||
actions: [
|
||||
SizedBox(
|
||||
width: double.infinity,
|
||||
child: OutlinedButton(
|
||||
onPressed: () => Navigator.pop(ctx, false),
|
||||
style: OutlinedButton.styleFrom(
|
||||
foregroundColor: kMuted,
|
||||
side: const BorderSide(color: kBorder),
|
||||
builder: (ctx) {
|
||||
bool cancelling = false;
|
||||
return StatefulBuilder(
|
||||
builder: (context, setDialog) {
|
||||
return AlertDialog(
|
||||
icon: Icon(Icons.warning_amber_rounded, color: kDanger, size: 28),
|
||||
title: const Text('Batalkan Transaksi?'),
|
||||
content: const Text(
|
||||
'Stok akan dikembalikan secara otomatis. Tindakan ini tidak dapat dibatalkan.',
|
||||
),
|
||||
child: const Text('Batal'),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
SizedBox(
|
||||
width: double.infinity,
|
||||
child: FilledButton(
|
||||
onPressed: () => Navigator.pop(ctx, true),
|
||||
style: FilledButton.styleFrom(
|
||||
backgroundColor: kDanger,
|
||||
),
|
||||
child: const Text('Batalkan'),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
actions: [
|
||||
Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: OutlinedButton(
|
||||
onPressed: cancelling ? null : () => Navigator.pop(ctx, false),
|
||||
style: OutlinedButton.styleFrom(
|
||||
foregroundColor: kMuted,
|
||||
side: const BorderSide(color: kBorder),
|
||||
),
|
||||
child: const Text('Batal'),
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 10),
|
||||
Expanded(
|
||||
child: FilledButton(
|
||||
onPressed: cancelling
|
||||
? null
|
||||
: () => Navigator.pop(ctx, true),
|
||||
style: FilledButton.styleFrom(backgroundColor: kDanger),
|
||||
child: cancelling
|
||||
? const SizedBox(height: 18, width: 18, child: CircularProgressIndicator(strokeWidth: 2, color: Colors.white))
|
||||
: const Text('Batalkan'),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
);
|
||||
},
|
||||
);
|
||||
if (confirm == true && mounted) {
|
||||
final err = await state.cancelSale(sale.id);
|
||||
if (confirm == true && mounted) {
|
||||
final err = await state.cancelSale(currentSale.id);
|
||||
if (mounted) {
|
||||
Navigator.pop(sheetContext);
|
||||
messenger.showSnackBar(
|
||||
@@ -802,6 +934,8 @@ class _RiwayatScreenState extends State<RiwayatScreen> {
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user