Implement printing status card and fix transaction screen issues
parent
9fe79d5ab7
commit
a2eedc8efc
|
@ -5,6 +5,35 @@ plugins {
|
||||||
id "dev.flutter.flutter-gradle-plugin"
|
id "dev.flutter.flutter-gradle-plugin"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
def localProperties = new Properties()
|
||||||
|
def localPropertiesFile = rootProject.file('local.properties')
|
||||||
|
if (localPropertiesFile.exists()) {
|
||||||
|
localPropertiesFile.withReader('UTF-8') { reader ->
|
||||||
|
localProperties.load(reader)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
def flutterRoot = localProperties.getProperty('flutter.sdk')
|
||||||
|
if (flutterRoot == null) {
|
||||||
|
throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.")
|
||||||
|
}
|
||||||
|
|
||||||
|
def flutterVersionCode = localProperties.getProperty('flutter.versionCode')
|
||||||
|
if (flutterVersionCode == null) {
|
||||||
|
flutterVersionCode = '1'
|
||||||
|
}
|
||||||
|
|
||||||
|
def flutterVersionName = localProperties.getProperty('flutter.versionName')
|
||||||
|
if (flutterVersionName == null) {
|
||||||
|
flutterVersionName = '1.0'
|
||||||
|
}
|
||||||
|
|
||||||
|
def keystoreProperties = new Properties()
|
||||||
|
def keystorePropertiesFile = rootProject.file('key.properties')
|
||||||
|
if (keystorePropertiesFile.exists()) {
|
||||||
|
keystoreProperties.load(new FileInputStream(keystorePropertiesFile))
|
||||||
|
}
|
||||||
|
|
||||||
android {
|
android {
|
||||||
namespace = "com.example.cashumit"
|
namespace = "com.example.cashumit"
|
||||||
compileSdk = 35
|
compileSdk = 35
|
||||||
|
@ -26,15 +55,22 @@ android {
|
||||||
// For more information, see: https://flutter.dev/to/review-gradle-config.
|
// For more information, see: https://flutter.dev/to/review-gradle-config.
|
||||||
minSdk = flutter.minSdkVersion
|
minSdk = flutter.minSdkVersion
|
||||||
targetSdk = flutter.targetSdkVersion
|
targetSdk = flutter.targetSdkVersion
|
||||||
versionCode = flutter.versionCode
|
versionCode = flutter.versionCode.toInteger()
|
||||||
versionName = flutter.versionName
|
versionName = flutter.versionName
|
||||||
}
|
}
|
||||||
|
|
||||||
|
signingConfigs {
|
||||||
|
release {
|
||||||
|
keyAlias keystoreProperties['keyAlias']
|
||||||
|
keyPassword keystoreProperties['keyPassword']
|
||||||
|
storeFile keystoreProperties['storeFile'] ? file(keystoreProperties['storeFile']) : null
|
||||||
|
storePassword keystoreProperties['storePassword']
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
buildTypes {
|
buildTypes {
|
||||||
release {
|
release {
|
||||||
// TODO: Add your own signing config for the release build.
|
signingConfig signingConfigs.release
|
||||||
// Signing with the debug keys for now, so `flutter run --release` works.
|
|
||||||
signingConfig = signingConfigs.debug
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,6 +6,7 @@ import 'package:cashumit/services/firefly_api_service.dart';
|
||||||
import 'package:bluetooth_print/bluetooth_print.dart';
|
import 'package:bluetooth_print/bluetooth_print.dart';
|
||||||
import 'package:bluetooth_print/bluetooth_print_model.dart';
|
import 'package:bluetooth_print/bluetooth_print_model.dart';
|
||||||
import 'package:cashumit/utils/currency_format.dart';
|
import 'package:cashumit/utils/currency_format.dart';
|
||||||
|
import 'package:cashumit/widgets/printing_status_card.dart';
|
||||||
import 'package:shared_preferences/shared_preferences.dart';
|
import 'package:shared_preferences/shared_preferences.dart';
|
||||||
|
|
||||||
class TransactionScreen extends StatefulWidget {
|
class TransactionScreen extends StatefulWidget {
|
||||||
|
@ -40,6 +41,9 @@ class _TransactionScreenState extends State<TransactionScreen> {
|
||||||
String? _destinationAccountName;
|
String? _destinationAccountName;
|
||||||
bool _isLoadingAccounts = false;
|
bool _isLoadingAccounts = false;
|
||||||
|
|
||||||
|
// Printing status
|
||||||
|
bool _isPrinting = false;
|
||||||
|
|
||||||
// Controllers for manual account input
|
// Controllers for manual account input
|
||||||
final TextEditingController _sourceAccountController = TextEditingController();
|
final TextEditingController _sourceAccountController = TextEditingController();
|
||||||
final TextEditingController _destinationAccountController = TextEditingController();
|
final TextEditingController _destinationAccountController = TextEditingController();
|
||||||
|
@ -451,6 +455,11 @@ class _TransactionScreenState extends State<TransactionScreen> {
|
||||||
|
|
||||||
if (confirmed != true) return;
|
if (confirmed != true) return;
|
||||||
|
|
||||||
|
// Tampilkan status printing
|
||||||
|
setState(() {
|
||||||
|
_isPrinting = true;
|
||||||
|
});
|
||||||
|
|
||||||
// Cetak struk
|
// Cetak struk
|
||||||
final printService = PrintService();
|
final printService = PrintService();
|
||||||
final printed = await printService.printTransaction(
|
final printed = await printService.printTransaction(
|
||||||
|
@ -459,6 +468,11 @@ class _TransactionScreenState extends State<TransactionScreen> {
|
||||||
'Jl. Merdeka No. 123, Jakarta',
|
'Jl. Merdeka No. 123, Jakarta',
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// Sembunyikan status printing
|
||||||
|
setState(() {
|
||||||
|
_isPrinting = false;
|
||||||
|
});
|
||||||
|
|
||||||
if (!printed) {
|
if (!printed) {
|
||||||
if (mounted) {
|
if (mounted) {
|
||||||
ScaffoldMessenger.of(context).showSnackBar(
|
ScaffoldMessenger.of(context).showSnackBar(
|
||||||
|
@ -507,224 +521,236 @@ class _TransactionScreenState extends State<TransactionScreen> {
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Scaffold(
|
return Stack(
|
||||||
appBar: AppBar(
|
children: [
|
||||||
title: const Text('Aplikasi Kasir'),
|
Scaffold(
|
||||||
actions: [
|
appBar: AppBar(
|
||||||
IconButton(
|
title: const Text('Aplikasi Kasir'),
|
||||||
onPressed: _loadAccounts,
|
actions: [
|
||||||
icon: _isLoadingAccounts
|
IconButton(
|
||||||
? const CircularProgressIndicator()
|
onPressed: _loadAccounts,
|
||||||
: const Icon(Icons.refresh),
|
icon: _isLoadingAccounts
|
||||||
),
|
? const CircularProgressIndicator()
|
||||||
IconButton(
|
: const Icon(Icons.refresh),
|
||||||
onPressed: _startScan,
|
|
||||||
icon: _isScanning
|
|
||||||
? const CircularProgressIndicator()
|
|
||||||
: const Icon(Icons.bluetooth),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
body: Column(
|
|
||||||
children: [
|
|
||||||
// Pencarian item
|
|
||||||
Padding(
|
|
||||||
padding: const EdgeInsets.all(8.0),
|
|
||||||
child: TextField(
|
|
||||||
controller: _searchController,
|
|
||||||
decoration: const InputDecoration(
|
|
||||||
labelText: 'Cari barang...',
|
|
||||||
prefixIcon: Icon(Icons.search),
|
|
||||||
border: OutlineInputBorder(),
|
|
||||||
),
|
),
|
||||||
onChanged: _searchItems,
|
IconButton(
|
||||||
),
|
onPressed: _startScan,
|
||||||
),
|
icon: _isScanning
|
||||||
// Dropdown printer
|
? const CircularProgressIndicator()
|
||||||
if (_devices.isNotEmpty)
|
: const Icon(Icons.bluetooth),
|
||||||
Padding(
|
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 8.0),
|
|
||||||
child: DropdownButton<BluetoothDevice>(
|
|
||||||
hint: const Text('Pilih Printer'),
|
|
||||||
value: _selectedDevice,
|
|
||||||
items: _devices
|
|
||||||
.map((device) => DropdownMenuItem(
|
|
||||||
value: device,
|
|
||||||
child: Text(device.name ?? device.address ?? '-'),
|
|
||||||
))
|
|
||||||
.toList(),
|
|
||||||
onChanged: (device) {
|
|
||||||
setState(() {
|
|
||||||
_selectedDevice = device;
|
|
||||||
});
|
|
||||||
},
|
|
||||||
isExpanded: true,
|
|
||||||
),
|
),
|
||||||
),
|
],
|
||||||
// Dropdown metode pembayaran
|
|
||||||
Padding(
|
|
||||||
padding: const EdgeInsets.all(8.0),
|
|
||||||
child: DropdownButton<String>(
|
|
||||||
value: _paymentMethod,
|
|
||||||
items: ['Tunai', 'Debit', 'Kredit', 'QRIS']
|
|
||||||
.map((method) => DropdownMenuItem(
|
|
||||||
value: method,
|
|
||||||
child: Text(method),
|
|
||||||
))
|
|
||||||
.toList(),
|
|
||||||
onChanged: (method) {
|
|
||||||
setState(() {
|
|
||||||
_paymentMethod = method!;
|
|
||||||
});
|
|
||||||
},
|
|
||||||
isExpanded: true,
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
// Transaction settings directly in this screen
|
body: Column(
|
||||||
Card(
|
children: [
|
||||||
margin: const EdgeInsets.all(8.0),
|
// Pencarian item
|
||||||
child: Padding(
|
Padding(
|
||||||
padding: const EdgeInsets.all(12.0),
|
padding: const EdgeInsets.all(8.0),
|
||||||
child: Column(
|
child: TextField(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
controller: _searchController,
|
||||||
children: [
|
decoration: const InputDecoration(
|
||||||
const Text(
|
labelText: 'Cari barang...',
|
||||||
'Pengaturan Transaksi:',
|
prefixIcon: Icon(Icons.search),
|
||||||
style: TextStyle(fontWeight: FontWeight.bold),
|
border: OutlineInputBorder(),
|
||||||
),
|
),
|
||||||
const SizedBox(height: 8),
|
onChanged: _searchItems,
|
||||||
// Date picker
|
),
|
||||||
const Text('Tanggal Transaksi:'),
|
|
||||||
ListTile(
|
|
||||||
title: Text(
|
|
||||||
'${_transactionDate.day}/${_transactionDate.month}/${_transactionDate.year}',
|
|
||||||
),
|
|
||||||
trailing: const Icon(Icons.calendar_today),
|
|
||||||
onTap: () => _selectDate(context),
|
|
||||||
),
|
|
||||||
const SizedBox(height: 8),
|
|
||||||
// Source account
|
|
||||||
const Text('Akun Sumber:'),
|
|
||||||
_sourceAccountId != null
|
|
||||||
? Card(
|
|
||||||
child: ListTile(
|
|
||||||
title: Text(_sourceAccountName ?? ''),
|
|
||||||
trailing: const Icon(Icons.edit),
|
|
||||||
onTap: _selectSourceAccount,
|
|
||||||
),
|
|
||||||
)
|
|
||||||
: Column(
|
|
||||||
children: [
|
|
||||||
TextField(
|
|
||||||
controller: _sourceAccountController,
|
|
||||||
decoration: const InputDecoration(
|
|
||||||
labelText: 'Nama Akun Sumber',
|
|
||||||
hintText: 'Ketik nama akun atau pilih dari daftar',
|
|
||||||
),
|
|
||||||
onChanged: _onSourceAccountChanged,
|
|
||||||
),
|
|
||||||
ElevatedButton(
|
|
||||||
onPressed: _selectSourceAccount,
|
|
||||||
child: const Text('Pilih Akun Sumber dari Daftar'),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
const SizedBox(height: 8),
|
|
||||||
// Destination account
|
|
||||||
const Text('Akun Tujuan:'),
|
|
||||||
_destinationAccountId != null
|
|
||||||
? Card(
|
|
||||||
child: ListTile(
|
|
||||||
title: Text(_destinationAccountName ?? ''),
|
|
||||||
trailing: const Icon(Icons.edit),
|
|
||||||
onTap: _selectDestinationAccount,
|
|
||||||
),
|
|
||||||
)
|
|
||||||
: Column(
|
|
||||||
children: [
|
|
||||||
TextField(
|
|
||||||
controller: _destinationAccountController,
|
|
||||||
decoration: const InputDecoration(
|
|
||||||
labelText: 'Nama Akun Tujuan',
|
|
||||||
hintText: 'Ketik nama akun atau pilih dari daftar',
|
|
||||||
),
|
|
||||||
onChanged: _onDestinationAccountChanged,
|
|
||||||
),
|
|
||||||
ElevatedButton(
|
|
||||||
onPressed: _selectDestinationAccount,
|
|
||||||
child: const Text('Pilih Akun Tujuan dari Daftar'),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
if (_isLoadingAccounts)
|
|
||||||
const Padding(
|
|
||||||
padding: EdgeInsets.all(8.0),
|
|
||||||
child: Center(child: CircularProgressIndicator()),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
),
|
||||||
),
|
// Dropdown printer
|
||||||
),
|
if (_devices.isNotEmpty)
|
||||||
// Total
|
Padding(
|
||||||
Container(
|
padding: const EdgeInsets.symmetric(horizontal: 8.0),
|
||||||
padding: const EdgeInsets.all(16.0),
|
child: DropdownButton<BluetoothDevice>(
|
||||||
color: Colors.grey[200],
|
hint: const Text('Pilih Printer'),
|
||||||
child: Row(
|
value: _selectedDevice,
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
items: _devices
|
||||||
children: [
|
.map((device) => DropdownMenuItem(
|
||||||
const Text(
|
value: device,
|
||||||
'Total:',
|
child: Text(device.name ?? device.address ?? '-'),
|
||||||
style: TextStyle(fontSize: 20, fontWeight: FontWeight.bold),
|
))
|
||||||
|
.toList(),
|
||||||
|
onChanged: (device) {
|
||||||
|
setState(() {
|
||||||
|
_selectedDevice = device;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
isExpanded: true,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
Text(
|
// Dropdown metode pembayaran
|
||||||
'Rp ${CurrencyFormat.formatRupiahWithoutSymbol(_total)}',
|
Padding(
|
||||||
style: const TextStyle(fontSize: 20, fontWeight: FontWeight.bold),
|
padding: const EdgeInsets.all(8.0),
|
||||||
|
child: DropdownButton<String>(
|
||||||
|
value: _paymentMethod,
|
||||||
|
items: ['Tunai', 'Debit', 'Kredit', 'QRIS']
|
||||||
|
.map((method) => DropdownMenuItem(
|
||||||
|
value: method,
|
||||||
|
child: Text(method),
|
||||||
|
))
|
||||||
|
.toList(),
|
||||||
|
onChanged: (method) {
|
||||||
|
setState(() {
|
||||||
|
_paymentMethod = method!;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
isExpanded: true,
|
||||||
),
|
),
|
||||||
],
|
),
|
||||||
),
|
// Transaction settings directly in this screen
|
||||||
),
|
Card(
|
||||||
// TabBar untuk navigasi
|
margin: const EdgeInsets.all(8.0),
|
||||||
Expanded(
|
child: Padding(
|
||||||
child: DefaultTabController(
|
padding: const EdgeInsets.all(12.0),
|
||||||
length: 2,
|
child: Column(
|
||||||
child: Column(
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
const TabBar(
|
const Text(
|
||||||
tabs: [
|
'Pengaturan Transaksi:',
|
||||||
Tab(text: 'Barang'),
|
style: TextStyle(fontWeight: FontWeight.bold),
|
||||||
Tab(text: 'Keranjang'),
|
),
|
||||||
|
const SizedBox(height: 8),
|
||||||
|
// Date picker
|
||||||
|
const Text('Tanggal Transaksi:'),
|
||||||
|
ListTile(
|
||||||
|
title: Text(
|
||||||
|
'${_transactionDate.day}/${_transactionDate.month}/${_transactionDate.year}',
|
||||||
|
),
|
||||||
|
trailing: const Icon(Icons.calendar_today),
|
||||||
|
onTap: () => _selectDate(context),
|
||||||
|
),
|
||||||
|
const SizedBox(height: 8),
|
||||||
|
// Source account
|
||||||
|
const Text('Akun Sumber:'),
|
||||||
|
_sourceAccountId != null
|
||||||
|
? Card(
|
||||||
|
child: ListTile(
|
||||||
|
title: Text(_sourceAccountName ?? ''),
|
||||||
|
trailing: const Icon(Icons.edit),
|
||||||
|
onTap: _selectSourceAccount,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
: Column(
|
||||||
|
children: [
|
||||||
|
TextField(
|
||||||
|
controller: _sourceAccountController,
|
||||||
|
decoration: const InputDecoration(
|
||||||
|
labelText: 'Nama Akun Sumber',
|
||||||
|
hintText: 'Ketik nama akun atau pilih dari daftar',
|
||||||
|
),
|
||||||
|
onChanged: _onSourceAccountChanged,
|
||||||
|
),
|
||||||
|
ElevatedButton(
|
||||||
|
onPressed: _selectSourceAccount,
|
||||||
|
child: const Text('Pilih Akun Sumber dari Daftar'),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
const SizedBox(height: 8),
|
||||||
|
// Destination account
|
||||||
|
const Text('Akun Tujuan:'),
|
||||||
|
_destinationAccountId != null
|
||||||
|
? Card(
|
||||||
|
child: ListTile(
|
||||||
|
title: Text(_destinationAccountName ?? ''),
|
||||||
|
trailing: const Icon(Icons.edit),
|
||||||
|
onTap: _selectDestinationAccount,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
: Column(
|
||||||
|
children: [
|
||||||
|
TextField(
|
||||||
|
controller: _destinationAccountController,
|
||||||
|
decoration: const InputDecoration(
|
||||||
|
labelText: 'Nama Akun Tujuan',
|
||||||
|
hintText: 'Ketik nama akun atau pilih dari daftar',
|
||||||
|
),
|
||||||
|
onChanged: _onDestinationAccountChanged,
|
||||||
|
),
|
||||||
|
ElevatedButton(
|
||||||
|
onPressed: _selectDestinationAccount,
|
||||||
|
child: const Text('Pilih Akun Tujuan dari Daftar'),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
if (_isLoadingAccounts)
|
||||||
|
const Padding(
|
||||||
|
padding: EdgeInsets.all(8.0),
|
||||||
|
child: Center(child: CircularProgressIndicator()),
|
||||||
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
Expanded(
|
),
|
||||||
child: TabBarView(
|
),
|
||||||
children: [
|
// Total
|
||||||
// Tab Barang
|
Container(
|
||||||
_buildItemsTab(),
|
padding: const EdgeInsets.all(16.0),
|
||||||
// Tab Keranjang
|
color: Colors.grey[200],
|
||||||
_buildCartTab(),
|
child: Row(
|
||||||
],
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
|
children: [
|
||||||
|
const Text(
|
||||||
|
'Total:',
|
||||||
|
style: TextStyle(fontSize: 20, fontWeight: FontWeight.bold),
|
||||||
),
|
),
|
||||||
|
Text(
|
||||||
|
'Rp ${CurrencyFormat.formatRupiahWithoutSymbol(_total)}',
|
||||||
|
style: const TextStyle(fontSize: 20, fontWeight: FontWeight.bold),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
// TabBar untuk navigasi
|
||||||
|
Expanded(
|
||||||
|
child: DefaultTabController(
|
||||||
|
length: 2,
|
||||||
|
child: Column(
|
||||||
|
children: [
|
||||||
|
const TabBar(
|
||||||
|
tabs: [
|
||||||
|
Tab(text: 'Barang'),
|
||||||
|
Tab(text: 'Keranjang'),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
Expanded(
|
||||||
|
child: TabBarView(
|
||||||
|
children: [
|
||||||
|
// Tab Barang
|
||||||
|
_buildItemsTab(),
|
||||||
|
// Tab Keranjang
|
||||||
|
_buildCartTab(),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
),
|
),
|
||||||
],
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
bottomNavigationBar: Padding(
|
||||||
|
padding: const EdgeInsets.all(8.0),
|
||||||
|
child: ElevatedButton(
|
||||||
|
onPressed: _completeTransaction,
|
||||||
|
style: ElevatedButton.styleFrom(
|
||||||
|
padding: const EdgeInsets.all(16.0),
|
||||||
|
backgroundColor: Colors.green,
|
||||||
|
),
|
||||||
|
child: const Text(
|
||||||
|
'BAYAR',
|
||||||
|
style: TextStyle(fontSize: 20, fontWeight: FontWeight.bold),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
|
||||||
),
|
|
||||||
bottomNavigationBar: Padding(
|
|
||||||
padding: const EdgeInsets.all(8.0),
|
|
||||||
child: ElevatedButton(
|
|
||||||
onPressed: _completeTransaction,
|
|
||||||
style: ElevatedButton.styleFrom(
|
|
||||||
padding: const EdgeInsets.all(16.0),
|
|
||||||
backgroundColor: Colors.green,
|
|
||||||
),
|
|
||||||
child: const Text(
|
|
||||||
'BAYAR',
|
|
||||||
style: TextStyle(fontSize: 20, fontWeight: FontWeight.bold),
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
),
|
PrintingStatusCard(
|
||||||
|
isVisible: _isPrinting,
|
||||||
|
onDismiss: () {
|
||||||
|
setState(() {
|
||||||
|
_isPrinting = false;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -5,10 +5,10 @@ class PrintingStatusCard extends StatefulWidget {
|
||||||
final VoidCallback? onDismiss;
|
final VoidCallback? onDismiss;
|
||||||
|
|
||||||
const PrintingStatusCard({
|
const PrintingStatusCard({
|
||||||
Key? key,
|
super.key,
|
||||||
required this.isVisible,
|
required this.isVisible,
|
||||||
this.onDismiss,
|
this.onDismiss,
|
||||||
}) : super(key: key);
|
}) : super();
|
||||||
|
|
||||||
@override
|
@override
|
||||||
State<PrintingStatusCard> createState() => _PrintingStatusCardState();
|
State<PrintingStatusCard> createState() => _PrintingStatusCardState();
|
||||||
|
@ -71,81 +71,84 @@ class _PrintingStatusCardState extends State<PrintingStatusCard>
|
||||||
return AnimatedBuilder(
|
return AnimatedBuilder(
|
||||||
animation: _controller,
|
animation: _controller,
|
||||||
builder: (context, child) {
|
builder: (context, child) {
|
||||||
return Positioned(
|
return Visibility(
|
||||||
top: 100,
|
visible: widget.isVisible,
|
||||||
left: MediaQuery.of(context).size.width * 0.1,
|
child: Positioned(
|
||||||
right: MediaQuery.of(context).size.width * 0.1,
|
top: 100,
|
||||||
child: IgnorePointer(
|
left: MediaQuery.of(context).size.width * 0.1,
|
||||||
ignoring: !widget.isVisible,
|
right: MediaQuery.of(context).size.width * 0.1,
|
||||||
child: Opacity(
|
child: IgnorePointer(
|
||||||
opacity: _fadeAnimation.value,
|
ignoring: !_fadeAnimation.value.isNaN && _fadeAnimation.value < 0.5,
|
||||||
child: Transform.scale(
|
child: Opacity(
|
||||||
scale: _scaleAnimation.value,
|
opacity: _fadeAnimation.value,
|
||||||
child: Card(
|
child: Transform.scale(
|
||||||
elevation: 12,
|
scale: _scaleAnimation.value,
|
||||||
shape: RoundedRectangleBorder(
|
child: Card(
|
||||||
borderRadius: BorderRadius.circular(20),
|
elevation: 12,
|
||||||
),
|
shape: RoundedRectangleBorder(
|
||||||
child: Container(
|
borderRadius: BorderRadius.circular(20),
|
||||||
padding: const EdgeInsets.all(20),
|
),
|
||||||
decoration: BoxDecoration(
|
child: Container(
|
||||||
borderRadius: BorderRadius.circular(20),
|
padding: const EdgeInsets.all(20),
|
||||||
gradient: const LinearGradient(
|
decoration: BoxDecoration(
|
||||||
begin: Alignment.topLeft,
|
borderRadius: BorderRadius.circular(20),
|
||||||
end: Alignment.bottomRight,
|
gradient: const LinearGradient(
|
||||||
colors: [
|
begin: Alignment.topLeft,
|
||||||
Color(0xFF6A11CB),
|
end: Alignment.bottomRight,
|
||||||
Color(0xFF2575FC),
|
colors: [
|
||||||
|
Color(0xFF6A11CB),
|
||||||
|
Color(0xFF2575FC),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
child: Row(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
children: [
|
||||||
|
const SizedBox(width: 8),
|
||||||
|
const Icon(
|
||||||
|
Icons.print,
|
||||||
|
color: Colors.white,
|
||||||
|
size: 36,
|
||||||
|
),
|
||||||
|
const SizedBox(width: 16),
|
||||||
|
Expanded(
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
children: [
|
||||||
|
const Text(
|
||||||
|
'Mencetak Struk',
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: 20,
|
||||||
|
fontWeight: FontWeight.bold,
|
||||||
|
color: Colors.white,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(height: 4),
|
||||||
|
const Text(
|
||||||
|
'Mohon tunggu...',
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: 16,
|
||||||
|
color: Colors.white70,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(height: 12),
|
||||||
|
LinearProgressIndicator(
|
||||||
|
backgroundColor: Colors.white30,
|
||||||
|
color: Colors.white,
|
||||||
|
minHeight: 6,
|
||||||
|
value: null,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
IconButton(
|
||||||
|
icon: const Icon(Icons.close, color: Colors.white70),
|
||||||
|
onPressed: widget.onDismiss,
|
||||||
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
child: Row(
|
|
||||||
mainAxisSize: MainAxisSize.min,
|
|
||||||
children: [
|
|
||||||
const SizedBox(width: 8),
|
|
||||||
const Icon(
|
|
||||||
Icons.print,
|
|
||||||
color: Colors.white,
|
|
||||||
size: 36,
|
|
||||||
),
|
|
||||||
const SizedBox(width: 16),
|
|
||||||
Expanded(
|
|
||||||
child: Column(
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
|
||||||
mainAxisSize: MainAxisSize.min,
|
|
||||||
children: [
|
|
||||||
const Text(
|
|
||||||
'Mencetak Struk',
|
|
||||||
style: TextStyle(
|
|
||||||
fontSize: 20,
|
|
||||||
fontWeight: FontWeight.bold,
|
|
||||||
color: Colors.white,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
const SizedBox(height: 4),
|
|
||||||
const Text(
|
|
||||||
'Mohon tunggu...',
|
|
||||||
style: TextStyle(
|
|
||||||
fontSize: 16,
|
|
||||||
color: Colors.white70,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
const SizedBox(height: 12),
|
|
||||||
LinearProgressIndicator(
|
|
||||||
backgroundColor: Colors.white30,
|
|
||||||
color: Colors.white,
|
|
||||||
minHeight: 6,
|
|
||||||
value: null,
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
IconButton(
|
|
||||||
icon: const Icon(Icons.close, color: Colors.white70),
|
|
||||||
onPressed: widget.onDismiss,
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|
Loading…
Reference in New Issue