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>>(
|
final result = await showDialog<Map<String, dynamic>>(
|
||||||
context: context,
|
context: context,
|
||||||
builder: (ctx) {
|
builder: (ctx) {
|
||||||
bool submitting = false;
|
|
||||||
return StatefulBuilder(
|
return StatefulBuilder(
|
||||||
builder: (context, setDialog) {
|
builder: (context, setDialog) {
|
||||||
return AlertDialog(
|
return AlertDialog(
|
||||||
@@ -201,7 +200,7 @@ class _KasirScreenState extends State<KasirScreen> {
|
|||||||
children: [
|
children: [
|
||||||
Expanded(
|
Expanded(
|
||||||
child: OutlinedButton(
|
child: OutlinedButton(
|
||||||
onPressed: submitting ? null : () => Navigator.pop(ctx),
|
onPressed: () => Navigator.pop(ctx),
|
||||||
style: OutlinedButton.styleFrom(
|
style: OutlinedButton.styleFrom(
|
||||||
foregroundColor: kMuted,
|
foregroundColor: kMuted,
|
||||||
side: const BorderSide(color: kBorder),
|
side: const BorderSide(color: kBorder),
|
||||||
@@ -212,9 +211,7 @@ class _KasirScreenState extends State<KasirScreen> {
|
|||||||
const SizedBox(width: 10),
|
const SizedBox(width: 10),
|
||||||
Expanded(
|
Expanded(
|
||||||
child: FilledButton(
|
child: FilledButton(
|
||||||
onPressed: submitting
|
onPressed: () {
|
||||||
? null
|
|
||||||
: () {
|
|
||||||
final name = nameCtrl.text.trim();
|
final name = nameCtrl.text.trim();
|
||||||
final price = (RupiahInputFormatter.getRawValue(priceCtrl.text) ?? 0).toDouble();
|
final price = (RupiahInputFormatter.getRawValue(priceCtrl.text) ?? 0).toDouble();
|
||||||
final qty = int.tryParse(qtyCtrl.text.trim()) ?? 1;
|
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)),
|
style: FilledButton.styleFrom(backgroundColor: kAccent, foregroundColor: const Color(0xFF06210F)),
|
||||||
child: submitting
|
child: const Text('Tambah'),
|
||||||
? const SizedBox(height: 18, width: 18, child: CircularProgressIndicator(strokeWidth: 2, color: Color(0xFF06210F)))
|
|
||||||
: const Text('Tambah'),
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
@@ -247,7 +242,7 @@ class _KasirScreenState extends State<KasirScreen> {
|
|||||||
for (int i = 0; i < (result['qty'] as int); i++) {
|
for (int i = 0; i < (result['qty'] as int); i++) {
|
||||||
state.addToCart(manualProduct);
|
state.addToCart(manualProduct);
|
||||||
}
|
}
|
||||||
if (mounted) {
|
if (context.mounted) {
|
||||||
ScaffoldMessenger.of(context).showSnackBar(
|
ScaffoldMessenger.of(context).showSnackBar(
|
||||||
SnackBar(
|
SnackBar(
|
||||||
content: Text('Pesanan manual ditambahkan: ${result['name']}'),
|
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 {
|
class _QtyButton extends StatelessWidget {
|
||||||
final IconData icon;
|
final IconData icon;
|
||||||
|
|||||||
@@ -338,25 +338,25 @@ void _showAddForm(BuildContext context, AppState state) {
|
|||||||
FocusNode(),
|
FocusNode(),
|
||||||
FocusNode(),
|
FocusNode(),
|
||||||
];
|
];
|
||||||
bool _listenersAdded = false;
|
bool listenersAdded = false;
|
||||||
final _sheetController = DraggableScrollableController();
|
final sheetController = DraggableScrollableController();
|
||||||
|
|
||||||
showModalBottomSheet(
|
showModalBottomSheet(
|
||||||
context: context,
|
context: context,
|
||||||
isScrollControlled: true,
|
isScrollControlled: true,
|
||||||
backgroundColor: Colors.transparent,
|
backgroundColor: Colors.transparent,
|
||||||
builder: (sheetContext) => DraggableScrollableSheet(
|
builder: (sheetContext) => DraggableScrollableSheet(
|
||||||
controller: _sheetController,
|
controller: sheetController,
|
||||||
initialChildSize: 0.65,
|
initialChildSize: 0.65,
|
||||||
minChildSize: 0.5,
|
minChildSize: 0.5,
|
||||||
maxChildSize: 0.92,
|
maxChildSize: 0.92,
|
||||||
builder: (_, scrollController) {
|
builder: (_, scrollController) {
|
||||||
if (!_listenersAdded) {
|
if (!listenersAdded) {
|
||||||
_listenersAdded = true;
|
listenersAdded = true;
|
||||||
for (final node in focusNodes) {
|
for (final node in focusNodes) {
|
||||||
node.addListener(() {
|
node.addListener(() {
|
||||||
if (node.hasFocus && context.mounted) {
|
if (node.hasFocus && context.mounted) {
|
||||||
_sheetController.animateTo(
|
sheetController.animateTo(
|
||||||
0.92,
|
0.92,
|
||||||
duration: const Duration(milliseconds: 300),
|
duration: const Duration(milliseconds: 300),
|
||||||
curve: Curves.easeOut,
|
curve: Curves.easeOut,
|
||||||
@@ -606,8 +606,8 @@ void _showEditDialog(BuildContext context, AppState state, Product product) {
|
|||||||
FocusNode(),
|
FocusNode(),
|
||||||
FocusNode(),
|
FocusNode(),
|
||||||
];
|
];
|
||||||
bool _listenersAdded = false;
|
bool listenersAdded = false;
|
||||||
final _sheetController = DraggableScrollableController();
|
final sheetController = DraggableScrollableController();
|
||||||
|
|
||||||
showModalBottomSheet(
|
showModalBottomSheet(
|
||||||
context: context,
|
context: context,
|
||||||
@@ -616,17 +616,17 @@ void _showEditDialog(BuildContext context, AppState state, Product product) {
|
|||||||
builder: (sheetContext) {
|
builder: (sheetContext) {
|
||||||
final bottomInset = MediaQuery.of(context).viewInsets.bottom;
|
final bottomInset = MediaQuery.of(context).viewInsets.bottom;
|
||||||
return DraggableScrollableSheet(
|
return DraggableScrollableSheet(
|
||||||
controller: _sheetController,
|
controller: sheetController,
|
||||||
initialChildSize: 0.65,
|
initialChildSize: 0.65,
|
||||||
minChildSize: 0.5,
|
minChildSize: 0.5,
|
||||||
maxChildSize: 0.92,
|
maxChildSize: 0.92,
|
||||||
builder: (_, scrollController) {
|
builder: (_, scrollController) {
|
||||||
if (!_listenersAdded) {
|
if (!listenersAdded) {
|
||||||
_listenersAdded = true;
|
listenersAdded = true;
|
||||||
for (final node in focusNodes) {
|
for (final node in focusNodes) {
|
||||||
node.addListener(() {
|
node.addListener(() {
|
||||||
if (node.hasFocus && context.mounted) {
|
if (node.hasFocus && context.mounted) {
|
||||||
_sheetController.animateTo(
|
sheetController.animateTo(
|
||||||
0.92,
|
0.92,
|
||||||
duration: const Duration(milliseconds: 300),
|
duration: const Duration(milliseconds: 300),
|
||||||
curve: Curves.easeOut,
|
curve: Curves.easeOut,
|
||||||
|
|||||||
@@ -211,7 +211,7 @@ class _RiwayatScreenState extends State<RiwayatScreen> {
|
|||||||
lastDate: DateTime.now(),
|
lastDate: DateTime.now(),
|
||||||
initialDateRange: _dateRange,
|
initialDateRange: _dateRange,
|
||||||
);
|
);
|
||||||
if (mounted && picked != null) {
|
if (picked != null && context.mounted) {
|
||||||
setState(() => _dateRange = picked);
|
setState(() => _dateRange = picked);
|
||||||
context.read<AppState>().resetPagination();
|
context.read<AppState>().resetPagination();
|
||||||
}
|
}
|
||||||
@@ -691,7 +691,6 @@ class _RiwayatScreenState extends State<RiwayatScreen> {
|
|||||||
final result = await showDialog<double>(
|
final result = await showDialog<double>(
|
||||||
context: parentContext,
|
context: parentContext,
|
||||||
builder: (ctx) {
|
builder: (ctx) {
|
||||||
bool submitting = false;
|
|
||||||
return StatefulBuilder(
|
return StatefulBuilder(
|
||||||
builder: (context, setDialog) {
|
builder: (context, setDialog) {
|
||||||
final isUnpaid = currentSale.paymentStatus == 'unpaid';
|
final isUnpaid = currentSale.paymentStatus == 'unpaid';
|
||||||
@@ -784,7 +783,7 @@ class _RiwayatScreenState extends State<RiwayatScreen> {
|
|||||||
children: [
|
children: [
|
||||||
Expanded(
|
Expanded(
|
||||||
child: OutlinedButton(
|
child: OutlinedButton(
|
||||||
onPressed: submitting ? null : () => Navigator.pop(ctx),
|
onPressed: () => Navigator.pop(ctx),
|
||||||
style: OutlinedButton.styleFrom(
|
style: OutlinedButton.styleFrom(
|
||||||
foregroundColor: kMuted,
|
foregroundColor: kMuted,
|
||||||
side: const BorderSide(color: kBorder),
|
side: const BorderSide(color: kBorder),
|
||||||
@@ -795,17 +794,13 @@ class _RiwayatScreenState extends State<RiwayatScreen> {
|
|||||||
const SizedBox(width: 10),
|
const SizedBox(width: 10),
|
||||||
Expanded(
|
Expanded(
|
||||||
child: FilledButton(
|
child: FilledButton(
|
||||||
onPressed: submitting
|
onPressed: () {
|
||||||
? null
|
|
||||||
: () {
|
|
||||||
final val = (RupiahInputFormatter.getRawValue(payCtrl.text) ?? 0).toDouble();
|
final val = (RupiahInputFormatter.getRawValue(payCtrl.text) ?? 0).toDouble();
|
||||||
if (val <= 0) return;
|
if (val <= 0) return;
|
||||||
Navigator.pop(ctx, val);
|
Navigator.pop(ctx, val);
|
||||||
},
|
},
|
||||||
style: FilledButton.styleFrom(backgroundColor: kSuccess, foregroundColor: const Color(0xFF06210F)),
|
style: FilledButton.styleFrom(backgroundColor: kSuccess, foregroundColor: const Color(0xFF06210F)),
|
||||||
child: submitting
|
child: const Text('Simpan'),
|
||||||
? const SizedBox(height: 18, width: 18, child: CircularProgressIndicator(strokeWidth: 2, color: Color(0xFF06210F)))
|
|
||||||
: const Text('Simpan'),
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
@@ -830,7 +825,7 @@ class _RiwayatScreenState extends State<RiwayatScreen> {
|
|||||||
if (sheetContext.mounted) {
|
if (sheetContext.mounted) {
|
||||||
Navigator.pop(sheetContext);
|
Navigator.pop(sheetContext);
|
||||||
}
|
}
|
||||||
if (mounted) {
|
if (parentContext.mounted) {
|
||||||
final messenger = ScaffoldMessenger.of(parentContext);
|
final messenger = ScaffoldMessenger.of(parentContext);
|
||||||
final msg = err == null
|
final msg = err == null
|
||||||
? isNowPaid
|
? isNowPaid
|
||||||
@@ -865,7 +860,6 @@ class _RiwayatScreenState extends State<RiwayatScreen> {
|
|||||||
final confirm = await showDialog<bool>(
|
final confirm = await showDialog<bool>(
|
||||||
context: parentContext,
|
context: parentContext,
|
||||||
builder: (ctx) {
|
builder: (ctx) {
|
||||||
bool cancelling = false;
|
|
||||||
return StatefulBuilder(
|
return StatefulBuilder(
|
||||||
builder: (context, setDialog) {
|
builder: (context, setDialog) {
|
||||||
return AlertDialog(
|
return AlertDialog(
|
||||||
@@ -879,7 +873,7 @@ class _RiwayatScreenState extends State<RiwayatScreen> {
|
|||||||
children: [
|
children: [
|
||||||
Expanded(
|
Expanded(
|
||||||
child: OutlinedButton(
|
child: OutlinedButton(
|
||||||
onPressed: cancelling ? null : () => Navigator.pop(ctx, false),
|
onPressed: () => Navigator.pop(ctx, false),
|
||||||
style: OutlinedButton.styleFrom(
|
style: OutlinedButton.styleFrom(
|
||||||
foregroundColor: kMuted,
|
foregroundColor: kMuted,
|
||||||
side: const BorderSide(color: kBorder),
|
side: const BorderSide(color: kBorder),
|
||||||
@@ -890,13 +884,9 @@ class _RiwayatScreenState extends State<RiwayatScreen> {
|
|||||||
const SizedBox(width: 10),
|
const SizedBox(width: 10),
|
||||||
Expanded(
|
Expanded(
|
||||||
child: FilledButton(
|
child: FilledButton(
|
||||||
onPressed: cancelling
|
onPressed: () => Navigator.pop(ctx, true),
|
||||||
? null
|
|
||||||
: () => Navigator.pop(ctx, true),
|
|
||||||
style: FilledButton.styleFrom(backgroundColor: kDanger),
|
style: FilledButton.styleFrom(backgroundColor: kDanger),
|
||||||
child: cancelling
|
child: const Text('Batalkan'),
|
||||||
? const SizedBox(height: 18, width: 18, child: CircularProgressIndicator(strokeWidth: 2, color: Colors.white))
|
|
||||||
: const Text('Batalkan'),
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
@@ -909,7 +899,7 @@ class _RiwayatScreenState extends State<RiwayatScreen> {
|
|||||||
);
|
);
|
||||||
if (confirm == true && mounted) {
|
if (confirm == true && mounted) {
|
||||||
final err = await state.cancelSale(currentSale.id);
|
final err = await state.cancelSale(currentSale.id);
|
||||||
if (mounted) {
|
if (sheetContext.mounted) {
|
||||||
Navigator.pop(sheetContext);
|
Navigator.pop(sheetContext);
|
||||||
messenger.showSnackBar(
|
messenger.showSnackBar(
|
||||||
SnackBar(
|
SnackBar(
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
import 'dart:convert';
|
import 'dart:convert';
|
||||||
|
import 'package:flutter/foundation.dart';
|
||||||
import 'package:shared_preferences/shared_preferences.dart';
|
import 'package:shared_preferences/shared_preferences.dart';
|
||||||
import 'package:connectivity_plus/connectivity_plus.dart';
|
import 'package:connectivity_plus/connectivity_plus.dart';
|
||||||
import 'package:supabase_flutter/supabase_flutter.dart';
|
import 'package:supabase_flutter/supabase_flutter.dart';
|
||||||
@@ -24,7 +25,7 @@ class OfflineQueueService {
|
|||||||
onTimeout: () => throw TimeoutException('${operation ?? 'Operasi'} timeout setelah $_timeout'),
|
onTimeout: () => throw TimeoutException('${operation ?? 'Operasi'} timeout setelah $_timeout'),
|
||||||
);
|
);
|
||||||
} on TimeoutException catch (e) {
|
} on TimeoutException catch (e) {
|
||||||
print('OfflineQueue timeout: $e');
|
debugPrint('OfflineQueue timeout: $e');
|
||||||
rethrow;
|
rethrow;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -264,14 +264,6 @@ class AppState extends ChangeNotifier {
|
|||||||
notifyListeners();
|
notifyListeners();
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> _initAuth() async {
|
|
||||||
final session = _supabase.auth.currentSession;
|
|
||||||
if (session != null) {
|
|
||||||
userId = session.user.id;
|
|
||||||
await _loadProfile();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<void> _loadProfile() async {
|
Future<void> _loadProfile() async {
|
||||||
if (userId == null) return;
|
if (userId == null) return;
|
||||||
try {
|
try {
|
||||||
|
|||||||
Reference in New Issue
Block a user