Bersihkan semua 20 analyzer issue: hapus _initAuth/_ProductCard/dead code, rename underscore var, print->debugPrint, perbaiki BuildContext async guard (analyze 0 issue)
This commit is contained in:
@@ -155,7 +155,6 @@ class _KasirScreenState extends State<KasirScreen> {
|
||||
final result = await showDialog<Map<String, dynamic>>(
|
||||
context: context,
|
||||
builder: (ctx) {
|
||||
bool submitting = false;
|
||||
return StatefulBuilder(
|
||||
builder: (context, setDialog) {
|
||||
return AlertDialog(
|
||||
@@ -201,7 +200,7 @@ class _KasirScreenState extends State<KasirScreen> {
|
||||
children: [
|
||||
Expanded(
|
||||
child: OutlinedButton(
|
||||
onPressed: submitting ? null : () => Navigator.pop(ctx),
|
||||
onPressed: () => Navigator.pop(ctx),
|
||||
style: OutlinedButton.styleFrom(
|
||||
foregroundColor: kMuted,
|
||||
side: const BorderSide(color: kBorder),
|
||||
@@ -212,9 +211,7 @@ class _KasirScreenState extends State<KasirScreen> {
|
||||
const SizedBox(width: 10),
|
||||
Expanded(
|
||||
child: FilledButton(
|
||||
onPressed: submitting
|
||||
? null
|
||||
: () {
|
||||
onPressed: () {
|
||||
final name = nameCtrl.text.trim();
|
||||
final price = (RupiahInputFormatter.getRawValue(priceCtrl.text) ?? 0).toDouble();
|
||||
final qty = int.tryParse(qtyCtrl.text.trim()) ?? 1;
|
||||
@@ -226,9 +223,7 @@ class _KasirScreenState extends State<KasirScreen> {
|
||||
});
|
||||
},
|
||||
style: FilledButton.styleFrom(backgroundColor: kAccent, foregroundColor: const Color(0xFF06210F)),
|
||||
child: submitting
|
||||
? const SizedBox(height: 18, width: 18, child: CircularProgressIndicator(strokeWidth: 2, color: Color(0xFF06210F)))
|
||||
: const Text('Tambah'),
|
||||
child: const Text('Tambah'),
|
||||
),
|
||||
),
|
||||
],
|
||||
@@ -247,7 +242,7 @@ class _KasirScreenState extends State<KasirScreen> {
|
||||
for (int i = 0; i < (result['qty'] as int); i++) {
|
||||
state.addToCart(manualProduct);
|
||||
}
|
||||
if (mounted) {
|
||||
if (context.mounted) {
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(
|
||||
content: Text('Pesanan manual ditambahkan: ${result['name']}'),
|
||||
@@ -1748,125 +1743,6 @@ class _KasirListTile extends StatelessWidget {
|
||||
}
|
||||
}
|
||||
|
||||
class _ProductCard extends StatelessWidget {
|
||||
final Product product;
|
||||
final double displayPrice;
|
||||
final bool isReseller;
|
||||
final VoidCallback onTap;
|
||||
const _ProductCard({
|
||||
required this.product,
|
||||
required this.displayPrice,
|
||||
required this.isReseller,
|
||||
required this.onTap,
|
||||
});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final out = product.stock <= 0;
|
||||
|
||||
return AbsorbPointer(
|
||||
absorbing: out,
|
||||
child: Opacity(
|
||||
opacity: out ? 0.5 : 1,
|
||||
child: InkWell(
|
||||
onTap: out ? null : onTap,
|
||||
borderRadius: BorderRadius.circular(kRadius),
|
||||
child: Container(
|
||||
padding: const EdgeInsets.all(14),
|
||||
decoration: BoxDecoration(
|
||||
color: kSurface2,
|
||||
borderRadius: BorderRadius.circular(kRadius),
|
||||
border: Border.all(color: kBorder),
|
||||
boxShadow: const [
|
||||
BoxShadow(
|
||||
color: Colors.black26,
|
||||
blurRadius: 8,
|
||||
offset: Offset(0, 4),
|
||||
),
|
||||
],
|
||||
),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Row(
|
||||
children: [
|
||||
_KasirAvatar(product: product, size: 36, radius: 18),
|
||||
const Spacer(),
|
||||
Container(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: 8, vertical: 3),
|
||||
decoration: BoxDecoration(
|
||||
color: out
|
||||
? kDanger.withValues(alpha: 0.15)
|
||||
: kSuccess.withValues(alpha: 0.12),
|
||||
borderRadius: BorderRadius.circular(20),
|
||||
),
|
||||
child: Text(
|
||||
out ? 'Habis' : 'Stok ${product.stock}',
|
||||
style: TextStyle(
|
||||
fontSize: 10,
|
||||
fontWeight: FontWeight.w600,
|
||||
color: out ? kDanger : kSuccess,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
const Spacer(),
|
||||
Text(
|
||||
product.name,
|
||||
style: const TextStyle(
|
||||
fontWeight: FontWeight.w600, fontSize: 14),
|
||||
maxLines: 2,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
Wrap(
|
||||
spacing: 6,
|
||||
children: [
|
||||
Container(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: 10, vertical: 5),
|
||||
decoration: BoxDecoration(
|
||||
color: kAccent.withValues(alpha: 0.12),
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
),
|
||||
child: Text(
|
||||
formatRupiah(displayPrice),
|
||||
style: TextStyle(
|
||||
color: kAccent,
|
||||
fontWeight: FontWeight.w800,
|
||||
fontSize: 13,
|
||||
),
|
||||
),
|
||||
),
|
||||
if (isReseller) ...[
|
||||
const SizedBox(width: 6),
|
||||
Container(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: 6, vertical: 2),
|
||||
decoration: BoxDecoration(
|
||||
color: kAccent.withValues(alpha: 0.15),
|
||||
borderRadius: BorderRadius.circular(6),
|
||||
),
|
||||
child: const Text('Reseller',
|
||||
style: TextStyle(
|
||||
fontSize: 9,
|
||||
fontWeight: FontWeight.w700,
|
||||
color: kAccent)),
|
||||
),
|
||||
],
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class _QtyButton extends StatelessWidget {
|
||||
final IconData icon;
|
||||
|
||||
@@ -338,25 +338,25 @@ void _showAddForm(BuildContext context, AppState state) {
|
||||
FocusNode(),
|
||||
FocusNode(),
|
||||
];
|
||||
bool _listenersAdded = false;
|
||||
final _sheetController = DraggableScrollableController();
|
||||
bool listenersAdded = false;
|
||||
final sheetController = DraggableScrollableController();
|
||||
|
||||
showModalBottomSheet(
|
||||
context: context,
|
||||
isScrollControlled: true,
|
||||
backgroundColor: Colors.transparent,
|
||||
builder: (sheetContext) => DraggableScrollableSheet(
|
||||
controller: _sheetController,
|
||||
controller: sheetController,
|
||||
initialChildSize: 0.65,
|
||||
minChildSize: 0.5,
|
||||
maxChildSize: 0.92,
|
||||
builder: (_, scrollController) {
|
||||
if (!_listenersAdded) {
|
||||
_listenersAdded = true;
|
||||
if (!listenersAdded) {
|
||||
listenersAdded = true;
|
||||
for (final node in focusNodes) {
|
||||
node.addListener(() {
|
||||
if (node.hasFocus && context.mounted) {
|
||||
_sheetController.animateTo(
|
||||
sheetController.animateTo(
|
||||
0.92,
|
||||
duration: const Duration(milliseconds: 300),
|
||||
curve: Curves.easeOut,
|
||||
@@ -606,8 +606,8 @@ void _showEditDialog(BuildContext context, AppState state, Product product) {
|
||||
FocusNode(),
|
||||
FocusNode(),
|
||||
];
|
||||
bool _listenersAdded = false;
|
||||
final _sheetController = DraggableScrollableController();
|
||||
bool listenersAdded = false;
|
||||
final sheetController = DraggableScrollableController();
|
||||
|
||||
showModalBottomSheet(
|
||||
context: context,
|
||||
@@ -616,17 +616,17 @@ void _showEditDialog(BuildContext context, AppState state, Product product) {
|
||||
builder: (sheetContext) {
|
||||
final bottomInset = MediaQuery.of(context).viewInsets.bottom;
|
||||
return DraggableScrollableSheet(
|
||||
controller: _sheetController,
|
||||
controller: sheetController,
|
||||
initialChildSize: 0.65,
|
||||
minChildSize: 0.5,
|
||||
maxChildSize: 0.92,
|
||||
builder: (_, scrollController) {
|
||||
if (!_listenersAdded) {
|
||||
_listenersAdded = true;
|
||||
if (!listenersAdded) {
|
||||
listenersAdded = true;
|
||||
for (final node in focusNodes) {
|
||||
node.addListener(() {
|
||||
if (node.hasFocus && context.mounted) {
|
||||
_sheetController.animateTo(
|
||||
sheetController.animateTo(
|
||||
0.92,
|
||||
duration: const Duration(milliseconds: 300),
|
||||
curve: Curves.easeOut,
|
||||
|
||||
@@ -211,7 +211,7 @@ class _RiwayatScreenState extends State<RiwayatScreen> {
|
||||
lastDate: DateTime.now(),
|
||||
initialDateRange: _dateRange,
|
||||
);
|
||||
if (mounted && picked != null) {
|
||||
if (picked != null && context.mounted) {
|
||||
setState(() => _dateRange = picked);
|
||||
context.read<AppState>().resetPagination();
|
||||
}
|
||||
@@ -691,7 +691,6 @@ class _RiwayatScreenState extends State<RiwayatScreen> {
|
||||
final result = await showDialog<double>(
|
||||
context: parentContext,
|
||||
builder: (ctx) {
|
||||
bool submitting = false;
|
||||
return StatefulBuilder(
|
||||
builder: (context, setDialog) {
|
||||
final isUnpaid = currentSale.paymentStatus == 'unpaid';
|
||||
@@ -784,7 +783,7 @@ class _RiwayatScreenState extends State<RiwayatScreen> {
|
||||
children: [
|
||||
Expanded(
|
||||
child: OutlinedButton(
|
||||
onPressed: submitting ? null : () => Navigator.pop(ctx),
|
||||
onPressed: () => Navigator.pop(ctx),
|
||||
style: OutlinedButton.styleFrom(
|
||||
foregroundColor: kMuted,
|
||||
side: const BorderSide(color: kBorder),
|
||||
@@ -795,17 +794,13 @@ class _RiwayatScreenState extends State<RiwayatScreen> {
|
||||
const SizedBox(width: 10),
|
||||
Expanded(
|
||||
child: FilledButton(
|
||||
onPressed: submitting
|
||||
? null
|
||||
: () {
|
||||
onPressed: () {
|
||||
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'),
|
||||
child: const Text('Simpan'),
|
||||
),
|
||||
),
|
||||
],
|
||||
@@ -830,7 +825,7 @@ class _RiwayatScreenState extends State<RiwayatScreen> {
|
||||
if (sheetContext.mounted) {
|
||||
Navigator.pop(sheetContext);
|
||||
}
|
||||
if (mounted) {
|
||||
if (parentContext.mounted) {
|
||||
final messenger = ScaffoldMessenger.of(parentContext);
|
||||
final msg = err == null
|
||||
? isNowPaid
|
||||
@@ -865,7 +860,6 @@ class _RiwayatScreenState extends State<RiwayatScreen> {
|
||||
final confirm = await showDialog<bool>(
|
||||
context: parentContext,
|
||||
builder: (ctx) {
|
||||
bool cancelling = false;
|
||||
return StatefulBuilder(
|
||||
builder: (context, setDialog) {
|
||||
return AlertDialog(
|
||||
@@ -879,7 +873,7 @@ class _RiwayatScreenState extends State<RiwayatScreen> {
|
||||
children: [
|
||||
Expanded(
|
||||
child: OutlinedButton(
|
||||
onPressed: cancelling ? null : () => Navigator.pop(ctx, false),
|
||||
onPressed: () => Navigator.pop(ctx, false),
|
||||
style: OutlinedButton.styleFrom(
|
||||
foregroundColor: kMuted,
|
||||
side: const BorderSide(color: kBorder),
|
||||
@@ -890,13 +884,9 @@ class _RiwayatScreenState extends State<RiwayatScreen> {
|
||||
const SizedBox(width: 10),
|
||||
Expanded(
|
||||
child: FilledButton(
|
||||
onPressed: cancelling
|
||||
? null
|
||||
: () => Navigator.pop(ctx, true),
|
||||
onPressed: () => 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'),
|
||||
child: const Text('Batalkan'),
|
||||
),
|
||||
),
|
||||
],
|
||||
@@ -909,7 +899,7 @@ class _RiwayatScreenState extends State<RiwayatScreen> {
|
||||
);
|
||||
if (confirm == true && mounted) {
|
||||
final err = await state.cancelSale(currentSale.id);
|
||||
if (mounted) {
|
||||
if (sheetContext.mounted) {
|
||||
Navigator.pop(sheetContext);
|
||||
messenger.showSnackBar(
|
||||
SnackBar(
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import 'dart:async';
|
||||
import 'dart:convert';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
import 'package:connectivity_plus/connectivity_plus.dart';
|
||||
import 'package:supabase_flutter/supabase_flutter.dart';
|
||||
@@ -24,7 +25,7 @@ class OfflineQueueService {
|
||||
onTimeout: () => throw TimeoutException('${operation ?? 'Operasi'} timeout setelah $_timeout'),
|
||||
);
|
||||
} on TimeoutException catch (e) {
|
||||
print('OfflineQueue timeout: $e');
|
||||
debugPrint('OfflineQueue timeout: $e');
|
||||
rethrow;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -264,14 +264,6 @@ class AppState extends ChangeNotifier {
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
Future<void> _initAuth() async {
|
||||
final session = _supabase.auth.currentSession;
|
||||
if (session != null) {
|
||||
userId = session.user.id;
|
||||
await _loadProfile();
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _loadProfile() async {
|
||||
if (userId == null) return;
|
||||
try {
|
||||
|
||||
Reference in New Issue
Block a user