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:
Onie
2026-10-18 15:16:14 +07:00
parent a3629a7d82
commit a52e0ea9b1
5 changed files with 27 additions and 168 deletions

View File

@@ -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;

View File

@@ -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,

View File

@@ -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(

View File

@@ -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;
}
}

View File

@@ -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 {