Files
app-grosir/test_syntax2.dart
2026-07-23 22:12:32 +07:00

239 lines
9.6 KiB
Dart

import 'package:flutter/material.dart';
void test(BuildContext context) {
final name = TextEditingController();
final barcode = TextEditingController();
final price = TextEditingController();
final priceReseller = TextEditingController();
final stock = TextEditingController();
final minStockCtrl = TextEditingController(text: '5');
final hargaPokokCtrl = TextEditingController();
final focusNodes = <FocusNode>[
FocusNode(),
FocusNode(),
FocusNode(),
FocusNode(),
FocusNode(),
FocusNode(),
FocusNode(),
];
final _scrollTimers = <FocusNode, Timer>{};
for (final node in focusNodes) {
node.addListener(() {
if (!node.hasFocus) {
_scrollTimers[node]?.cancel();
_scrollTimers.remove(node);
} else if (context.mounted) {
_scrollTimers[node]?.cancel();
_scrollTimers[node] = Timer(const Duration(milliseconds: 350), () {
if (node.context != null && node.context!.mounted) {
Scrollable.ensureVisible(
node.context!,
duration: const Duration(milliseconds: 250),
alignment: 0.1,
);
}
_scrollTimers.remove(node);
});
}
});
}
final _scrollController = ScrollController();
showModalBottomSheet(
context: context,
isScrollControlled: true,
backgroundColor: Colors.transparent,
builder: (sheetContext) {
final bottomInset = MediaQuery.of(context).viewInsets.bottom;
return Container(
constraints: BoxConstraints(
maxHeight: MediaQuery.of(context).size.height * 0.92 - bottomInset,
),
decoration: const BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.vertical(top: Radius.circular(24)),
border: Border(top: BorderSide(color: Colors.grey)),
),
child: Column(
children: [
Container(
margin: const EdgeInsets.only(top: 12),
width: 40,
height: 4,
decoration: BoxDecoration(
color: Colors.grey,
borderRadius: BorderRadius.circular(4),
),
),
Padding(
padding: const EdgeInsets.fromLTRB(16, 12, 16, 4),
child: Row(
children: [
const Icon(Icons.add_box_outlined, color: Colors.amber),
const SizedBox(width: 8),
const Text('Tambah Produk',
style: TextStyle(
fontSize: 16, fontWeight: FontWeight.w700)),
const Spacer(),
IconButton(
icon: const Icon(Icons.close, color: Colors.grey),
onPressed: () => Navigator.pop(sheetContext),
tooltip: 'Tutup',
),
],
),
),
const Divider(height: 12),
Expanded(
child: SingleChildScrollView(
controller: _scrollController,
padding: EdgeInsets.fromLTRB(16, 8, 16, 16 + bottomInset),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
TextField(
controller: barcode,
focusNode: focusNodes[0],
decoration: InputDecoration(
labelText: 'Barcode / No. Produk',
prefixIcon: const Icon(Icons.qr_code_2_outlined),
suffixIcon: IconButton(
icon: const Icon(Icons.qr_code_scanner_outlined, color: Colors.amber),
onPressed: () async {
final code = await Navigator.push<String>(
context,
MaterialPageRoute(
builder: (_) => const Scaffold(body: Center(child: Text('Scan'))),
),
);
if (code != null && context.mounted) {
barcode.text = code;
}
},
tooltip: 'Scan barcode',
)),
),
const SizedBox(height: 10),
TextField(
controller: name,
focusNode: focusNodes[1],
decoration: const InputDecoration(
labelText: 'Nama produk',
prefixIcon: Icon(Icons.label_outline)),
),
const SizedBox(height: 10),
Row(
children: [
Expanded(
child: TextField(
controller: price,
focusNode: focusNodes[2],
keyboardType: TextInputType.number,
decoration: const InputDecoration(
labelText: 'Harga Umum',
prefixText: 'Rp ',
),
),
),
const SizedBox(width: 10),
Expanded(
child: TextField(
controller: priceReseller,
focusNode: focusNodes[3],
keyboardType: TextInputType.number,
decoration: const InputDecoration(
labelText: 'Harga Reseller',
prefixText: 'Rp ',
),
),
),
],
),
const SizedBox(height: 10),
TextField(
controller: stock,
focusNode: focusNodes[4],
keyboardType: TextInputType.number,
decoration: const InputDecoration(
labelText: 'Stok awal',
prefixIcon: Icon(Icons.numbers),
),
),
const SizedBox(height: 10),
TextField(
controller: hargaPokokCtrl,
focusNode: focusNodes[5],
keyboardType: TextInputType.number,
decoration: const InputDecoration(
labelText: 'Harga Pokok (modal)',
prefixText: 'Rp ',
helperText: 'Kosongkan jika tidak diketahui',
),
),
const SizedBox(height: 10),
TextField(
controller: minStockCtrl,
focusNode: focusNodes[6],
keyboardType: TextInputType.number,
decoration: const InputDecoration(
labelText: 'Stok minimum (warning)',
prefixIcon: Icon(Icons.warning_outlined),
helperText: 'Default: 5',
),
),
const SizedBox(height: 16),
SizedBox(
width: double.infinity,
child: FilledButton.icon(
onPressed: () async {
final n = name.text.trim();
final bc = barcode.text.trim();
final pr = (price.text.isEmpty ? 0 : double.tryParse(price.text) ?? 0);
final prR = (priceReseller.text.isEmpty ? pr : double.tryParse(priceReseller.text) ?? pr);
final st = int.tryParse(stock.text) ?? 0;
final ms = int.tryParse(minStockCtrl.text) ?? 5;
final hp = (hargaPokokCtrl.text.isEmpty ? 0 : double.tryParse(hargaPokokCtrl.text) ?? 0);
if (n.isEmpty || pr <= 0) return;
final err = 'OK'; // await state.addProduct(n, bc, pr, prR, st, ms, hp);
if (!context.mounted) return;
final messenger = ScaffoldMessenger.of(context);
if (err == null) {
name.clear();
barcode.clear();
price.clear();
priceReseller.clear();
stock.clear();
minStockCtrl.clear();
hargaPokokCtrl.clear();
messenger.showSnackBar(
const SnackBar(
content: Text('Produk berhasil ditambahkan'),
backgroundColor: Colors.green,
),
);
Navigator.pop(sheetContext);
} else {
messenger.showSnackBar(
SnackBar(
content: Text('Gagal menambah produk: $err'),
backgroundColor: Colors.red,
),
);
}
},
icon: const Icon(Icons.add),
label: const Text('Tambah Produk'),
),
),
],
),
),
],
),
);
},
);
}