267 lines
10 KiB
Dart
267 lines
10 KiB
Dart
import 'package:flutter/material.dart';
|
|
import 'package:flutter_speed_dial/flutter_speed_dial.dart';
|
|
import 'package:cashumit/services/bluetooth_service.dart';
|
|
import 'package:provider/provider.dart';
|
|
import 'package:cashumit/providers/receipt_provider.dart';
|
|
|
|
class ReceiptSpeedDial extends StatelessWidget {
|
|
final BluetoothService bluetoothService;
|
|
final Future<bool> Function() onCheckConnection;
|
|
final Future<void> Function() onPrint;
|
|
final VoidCallback onSettings;
|
|
final bool hasItems;
|
|
final bool allGroupsHaveSource;
|
|
final bool hasDestination;
|
|
final Future<void> Function() onSendToFirefly;
|
|
final VoidCallback onPrintingStart;
|
|
final VoidCallback onPrintingEnd;
|
|
final Future<void> Function()? onSendAndPrint;
|
|
|
|
const ReceiptSpeedDial({
|
|
super.key,
|
|
required this.bluetoothService,
|
|
required this.onCheckConnection,
|
|
required this.onPrint,
|
|
required this.onSettings,
|
|
required this.hasItems,
|
|
required this.allGroupsHaveSource,
|
|
required this.hasDestination,
|
|
required this.onSendToFirefly,
|
|
required this.onPrintingStart,
|
|
required this.onPrintingEnd,
|
|
this.onSendAndPrint,
|
|
});
|
|
|
|
bool get _canSubmit =>
|
|
hasItems && allGroupsHaveSource && hasDestination;
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
final primaryColor = Theme.of(context).colorScheme.primary;
|
|
|
|
return SpeedDial(
|
|
icon: Icons.menu,
|
|
activeIcon: Icons.close,
|
|
spacing: 6,
|
|
spaceBetweenChildren: 8,
|
|
backgroundColor: primaryColor,
|
|
foregroundColor: Colors.white,
|
|
activeBackgroundColor: Colors.red.shade600,
|
|
activeForegroundColor: Colors.white,
|
|
elevation: 4,
|
|
children: [
|
|
if (onSendAndPrint != null)
|
|
SpeedDialChild(
|
|
child: const Icon(Icons.done_all, color: Colors.white),
|
|
label: 'Kirim & Cetak Sekaligus',
|
|
labelStyle: const TextStyle(
|
|
fontWeight: FontWeight.bold,
|
|
color: Color(0xFF004D40),
|
|
),
|
|
labelBackgroundColor: const Color(0xFFE0F2F1),
|
|
backgroundColor: const Color(0xFF00897B),
|
|
onTap: _canSubmit
|
|
? onSendAndPrint
|
|
: () {
|
|
ScaffoldMessenger.of(context).showSnackBar(
|
|
SnackBar(
|
|
content: Text(!hasDestination
|
|
? 'Pilih akun tujuan terlebih dahulu'
|
|
: !allGroupsHaveSource
|
|
? 'Setiap grup harus punya akun sumber'
|
|
: 'Tambahkan item terlebih dahulu'),
|
|
duration: const Duration(seconds: 2),
|
|
),
|
|
);
|
|
},
|
|
),
|
|
SpeedDialChild(
|
|
child: const Icon(Icons.send_rounded, color: Colors.white),
|
|
label: 'Kirim ke Firefly',
|
|
labelStyle: const TextStyle(
|
|
fontWeight: FontWeight.bold,
|
|
color: Color(0xFF0D47A1),
|
|
),
|
|
labelBackgroundColor: const Color(0xFFE3F2FD),
|
|
backgroundColor: const Color(0xFF1E88E5),
|
|
onTap: _canSubmit
|
|
? onSendToFirefly
|
|
: () {
|
|
ScaffoldMessenger.of(context).showSnackBar(
|
|
SnackBar(
|
|
content: Text(!hasDestination
|
|
? 'Pilih akun tujuan terlebih dahulu'
|
|
: !allGroupsHaveSource
|
|
? 'Setiap grup harus punya akun sumber'
|
|
: 'Tambahkan item terlebih dahulu'),
|
|
duration: const Duration(seconds: 2),
|
|
),
|
|
);
|
|
},
|
|
),
|
|
SpeedDialChild(
|
|
child: bluetoothService.isPrinting
|
|
? const SizedBox(
|
|
width: 20,
|
|
height: 20,
|
|
child: CircularProgressIndicator(
|
|
color: Colors.white, strokeWidth: 2),
|
|
)
|
|
: const Icon(Icons.print_rounded, color: Colors.white),
|
|
label: 'Cetak Struk Saja',
|
|
labelStyle: const TextStyle(
|
|
fontWeight: FontWeight.bold,
|
|
color: Color(0xFF4A148C),
|
|
),
|
|
labelBackgroundColor: const Color(0xFFEDE7F6),
|
|
backgroundColor: const Color(0xFF7E57C2),
|
|
onTap: bluetoothService.isPrinting
|
|
? null
|
|
: () async {
|
|
onPrintingStart();
|
|
|
|
try {
|
|
final isConnected = await onCheckConnection();
|
|
if (isConnected) {
|
|
await onPrint();
|
|
} else {
|
|
if (bluetoothService.connectedDevice != null) {
|
|
ScaffoldMessenger.of(context).showSnackBar(
|
|
const SnackBar(
|
|
content:
|
|
Text('Mencoba menyambungkan ke printer...')),
|
|
);
|
|
try {
|
|
bool connectResult =
|
|
await bluetoothService.connectToDevice(
|
|
bluetoothService.connectedDevice!);
|
|
if (!connectResult) {
|
|
throw Exception('Gagal menyambungkan ke printer');
|
|
}
|
|
await Future.delayed(
|
|
const Duration(milliseconds: 500));
|
|
final isConnectedAfterConnect =
|
|
await onCheckConnection();
|
|
if (isConnectedAfterConnect) {
|
|
await onPrint();
|
|
} else {
|
|
ScaffoldMessenger.of(context).showSnackBar(
|
|
const SnackBar(
|
|
content:
|
|
Text('Gagal menyambungkan ke printer')),
|
|
);
|
|
}
|
|
} catch (e) {
|
|
ScaffoldMessenger.of(context).showSnackBar(
|
|
SnackBar(
|
|
content:
|
|
Text('Gagal menyambungkan ke printer: $e')),
|
|
);
|
|
}
|
|
} else {
|
|
ScaffoldMessenger.of(context).showSnackBar(
|
|
const SnackBar(
|
|
content:
|
|
Text('Hubungkan printer terlebih dahulu')),
|
|
);
|
|
}
|
|
}
|
|
} catch (e) {
|
|
ScaffoldMessenger.of(context).showSnackBar(
|
|
SnackBar(content: Text('Terjadi kesalahan: $e')),
|
|
);
|
|
} finally {
|
|
onPrintingEnd();
|
|
}
|
|
},
|
|
),
|
|
SpeedDialChild(
|
|
child: const Icon(Icons.bookmark_added_rounded, color: Colors.white),
|
|
label: 'Simpan Nanti (Offline)',
|
|
labelStyle: const TextStyle(
|
|
fontWeight: FontWeight.bold,
|
|
color: Color(0xFFE65100),
|
|
),
|
|
labelBackgroundColor: const Color(0xFFFFF3E0),
|
|
backgroundColor: const Color(0xFFEF6C00),
|
|
onTap: _canSubmit
|
|
? () async {
|
|
final receiptProvider = context.read<ReceiptProvider>();
|
|
try {
|
|
final receiptId =
|
|
await receiptProvider.saveTransactionLocally();
|
|
if (receiptId != null) {
|
|
if (context.mounted) {
|
|
ScaffoldMessenger.of(context).showSnackBar(
|
|
const SnackBar(
|
|
content: Text(
|
|
'Nota berhasil disimpan untuk dikirim nanti'),
|
|
),
|
|
);
|
|
}
|
|
}
|
|
} catch (e) {
|
|
if (context.mounted) {
|
|
ScaffoldMessenger.of(context).showSnackBar(
|
|
SnackBar(
|
|
content: Text('Gagal menyimpan nota: $e'),
|
|
),
|
|
);
|
|
}
|
|
}
|
|
}
|
|
: () {
|
|
ScaffoldMessenger.of(context).showSnackBar(
|
|
SnackBar(
|
|
content: Text(!hasDestination
|
|
? 'Pilih akun tujuan terlebih dahulu'
|
|
: !allGroupsHaveSource
|
|
? 'Setiap grup harus punya akun sumber'
|
|
: 'Tambahkan item terlebih dahulu'),
|
|
duration: const Duration(seconds: 2),
|
|
),
|
|
);
|
|
},
|
|
),
|
|
SpeedDialChild(
|
|
child: const Icon(Icons.assessment_outlined, color: Colors.white),
|
|
label: 'Laporan Keuangan',
|
|
labelStyle: const TextStyle(
|
|
fontWeight: FontWeight.bold,
|
|
color: Color(0xFF14532D),
|
|
),
|
|
labelBackgroundColor: const Color(0xFFDCFCE7),
|
|
backgroundColor: const Color(0xFF16A34A),
|
|
onTap: () {
|
|
Navigator.pushNamed(context, '/report');
|
|
},
|
|
),
|
|
SpeedDialChild(
|
|
child: const Icon(Icons.folder_copy_outlined, color: Colors.white),
|
|
label: 'Laporan Tersimpan',
|
|
labelStyle: const TextStyle(
|
|
fontWeight: FontWeight.bold,
|
|
color: Color(0xFF065F46),
|
|
),
|
|
labelBackgroundColor: const Color(0xFFD1FAE5),
|
|
backgroundColor: const Color(0xFF059669),
|
|
onTap: () {
|
|
Navigator.pushNamed(context, '/saved-reports');
|
|
},
|
|
),
|
|
SpeedDialChild(
|
|
child: const Icon(Icons.settings_rounded, color: Colors.white),
|
|
label: 'Pengaturan Server',
|
|
labelStyle: const TextStyle(
|
|
fontWeight: FontWeight.bold,
|
|
color: Color(0xFF263238),
|
|
),
|
|
labelBackgroundColor: const Color(0xFFECEFF1),
|
|
backgroundColor: const Color(0xFF546E7A),
|
|
onTap: onSettings,
|
|
),
|
|
],
|
|
);
|
|
}
|
|
}
|