263 lines
8.6 KiB
Dart
263 lines
8.6 KiB
Dart
import 'package:flutter/material.dart';
|
|
import 'package:provider/provider.dart';
|
|
import 'package:shared_preferences/shared_preferences.dart';
|
|
|
|
import '../state/app_state.dart';
|
|
import '../utils/colors.dart';
|
|
import 'kelola_kasir_screen.dart';
|
|
import 'printer_screen.dart';
|
|
|
|
class PengaturanScreen extends StatefulWidget {
|
|
const PengaturanScreen({super.key});
|
|
|
|
@override
|
|
State<PengaturanScreen> createState() => _PengaturanScreenState();
|
|
}
|
|
|
|
class _PengaturanScreenState extends State<PengaturanScreen> {
|
|
final TextEditingController _storeNameCtrl = TextEditingController();
|
|
final TextEditingController _currencyCtrl = TextEditingController(text: 'IDR');
|
|
final TextEditingController _whatsappCtrl = TextEditingController();
|
|
final TextEditingController _notesCtrl = TextEditingController();
|
|
bool _resellerEnabled = true;
|
|
bool _loading = true;
|
|
|
|
@override
|
|
void initState() {
|
|
super.initState();
|
|
_loadSettings();
|
|
}
|
|
|
|
Future<void> _loadSettings() async {
|
|
final prefs = await SharedPreferences.getInstance();
|
|
setState(() {
|
|
_storeNameCtrl.text = prefs.getString('store_name') ?? 'Toko Grosir';
|
|
_currencyCtrl.text = prefs.getString('currency') ?? 'IDR';
|
|
_whatsappCtrl.text = prefs.getString('store_whatsapp') ?? '';
|
|
_notesCtrl.text = prefs.getString('store_notes') ?? '';
|
|
_resellerEnabled = prefs.getBool('reseller_enabled') ?? true;
|
|
_loading = false;
|
|
});
|
|
}
|
|
|
|
Future<void> _saveSettings() async {
|
|
final prefs = await SharedPreferences.getInstance();
|
|
await prefs.setString('store_name', _storeNameCtrl.text.trim());
|
|
await prefs.setString('currency', _currencyCtrl.text.trim());
|
|
await prefs.setString('store_whatsapp', _whatsappCtrl.text.trim());
|
|
await prefs.setString('store_notes', _notesCtrl.text.trim());
|
|
await prefs.setBool('reseller_enabled', _resellerEnabled);
|
|
if (!mounted) return;
|
|
final state = context.read<AppState>();
|
|
state.setResellerEnabled(_resellerEnabled);
|
|
}
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
if (_loading) {
|
|
return const Center(child: CircularProgressIndicator(color: kAccent));
|
|
}
|
|
|
|
return RefreshIndicator(
|
|
onRefresh: () async {
|
|
context.read<AppState>().recordManualRefresh();
|
|
await context.read<AppState>().refresh();
|
|
},
|
|
color: kAccent,
|
|
child: ListView(
|
|
padding: const EdgeInsets.all(12),
|
|
children: [
|
|
_SettingsListTile(
|
|
icon: Icons.store_outlined,
|
|
title: 'Pengaturan Toko',
|
|
subtitle: _whatsappCtrl.text.isEmpty
|
|
? '${_storeNameCtrl.text} • ${_currencyCtrl.text}'
|
|
: '${_storeNameCtrl.text} • ${_currencyCtrl.text} • ${_whatsappCtrl.text}',
|
|
onTap: () => _showStoreSettingsDialog(context),
|
|
),
|
|
const SizedBox(height: 8),
|
|
_SettingsListTile(
|
|
icon: Icons.people_outline,
|
|
title: 'Akun Kasir',
|
|
subtitle: 'Tambah, edit, atau hapus akun kasir',
|
|
onTap: () {
|
|
Navigator.push(
|
|
context,
|
|
MaterialPageRoute(
|
|
builder: (_) => const KelolaKasirScreen(),
|
|
),
|
|
);
|
|
},
|
|
),
|
|
const SizedBox(height: 8),
|
|
_SettingsListTile(
|
|
icon: Icons.print_outlined,
|
|
title: 'Printer Bluetooth',
|
|
subtitle: 'Scan, connect, dan cetak struk',
|
|
onTap: () {
|
|
Navigator.push(
|
|
context,
|
|
MaterialPageRoute(
|
|
builder: (_) => const PrinterScreen(),
|
|
),
|
|
);
|
|
},
|
|
),
|
|
],
|
|
),
|
|
);
|
|
}
|
|
|
|
Future<void> _showStoreSettingsDialog(BuildContext context) async {
|
|
final storeNameCtrl = TextEditingController(text: _storeNameCtrl.text);
|
|
final currencyCtrl = TextEditingController(text: _currencyCtrl.text);
|
|
final whatsappCtrl = TextEditingController(text: _whatsappCtrl.text);
|
|
final notesCtrl = TextEditingController(text: _notesCtrl.text);
|
|
bool resellerEnabled = _resellerEnabled;
|
|
|
|
final messenger = ScaffoldMessenger.of(context);
|
|
|
|
final result = await showDialog<bool>(
|
|
context: context,
|
|
builder: (ctx) => StatefulBuilder(
|
|
builder: (ctx, setModalState) => AlertDialog(
|
|
title: const Text('Pengaturan Toko'),
|
|
content: SingleChildScrollView(
|
|
child: Column(
|
|
mainAxisSize: MainAxisSize.min,
|
|
children: [
|
|
TextField(
|
|
controller: storeNameCtrl,
|
|
decoration: const InputDecoration(
|
|
labelText: 'Nama Toko',
|
|
prefixIcon: Icon(Icons.badge_outlined),
|
|
),
|
|
),
|
|
const SizedBox(height: 10),
|
|
TextField(
|
|
controller: currencyCtrl,
|
|
decoration: const InputDecoration(
|
|
labelText: 'Mata Uang',
|
|
prefixIcon: Icon(Icons.money_outlined),
|
|
),
|
|
),
|
|
const SizedBox(height: 10),
|
|
TextField(
|
|
controller: whatsappCtrl,
|
|
keyboardType: TextInputType.phone,
|
|
decoration: const InputDecoration(
|
|
labelText: 'No. WhatsApp',
|
|
prefixIcon: Icon(Icons.phone_outlined),
|
|
helperText: 'Contoh: 081234567890',
|
|
),
|
|
),
|
|
const SizedBox(height: 10),
|
|
TextField(
|
|
controller: notesCtrl,
|
|
maxLines: 3,
|
|
decoration: const InputDecoration(
|
|
labelText: 'Catatan Tambahan',
|
|
prefixIcon: Icon(Icons.notes_outlined),
|
|
helperText: 'Opsional, akan dicetak di struk',
|
|
),
|
|
),
|
|
const SizedBox(height: 10),
|
|
SwitchListTile(
|
|
contentPadding: EdgeInsets.zero,
|
|
title: const Text('Mode Reseller Aktif',
|
|
style: TextStyle(fontSize: 14)),
|
|
subtitle: const Text(
|
|
'Jika aktif, kasir bisa toggle harga reseller per transaksi',
|
|
style: TextStyle(fontSize: 12, color: kMuted)),
|
|
value: resellerEnabled,
|
|
onChanged: (v) => setModalState(() => resellerEnabled = v),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
actions: [
|
|
TextButton(
|
|
onPressed: () => Navigator.pop(ctx, false),
|
|
child: const Text('Batal'),
|
|
),
|
|
FilledButton.icon(
|
|
onPressed: () async {
|
|
_storeNameCtrl.text = storeNameCtrl.text.trim();
|
|
_currencyCtrl.text = currencyCtrl.text.trim();
|
|
_whatsappCtrl.text = whatsappCtrl.text.trim();
|
|
_notesCtrl.text = notesCtrl.text.trim();
|
|
_resellerEnabled = resellerEnabled;
|
|
await _saveSettings();
|
|
if (ctx.mounted) {
|
|
Navigator.pop(ctx, true);
|
|
}
|
|
},
|
|
icon: const Icon(Icons.save_outlined, size: 18),
|
|
label: const Text('Simpan'),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
);
|
|
|
|
if (result == true && mounted) {
|
|
messenger.showSnackBar(
|
|
const SnackBar(
|
|
content: Text('Pengaturan tersimpan'),
|
|
backgroundColor: kSuccess,
|
|
),
|
|
);
|
|
}
|
|
}
|
|
|
|
@override
|
|
void dispose() {
|
|
_storeNameCtrl.dispose();
|
|
_currencyCtrl.dispose();
|
|
_whatsappCtrl.dispose();
|
|
_notesCtrl.dispose();
|
|
super.dispose();
|
|
}
|
|
}
|
|
|
|
class _SettingsListTile extends StatelessWidget {
|
|
final IconData icon;
|
|
final String title;
|
|
final String subtitle;
|
|
final VoidCallback onTap;
|
|
const _SettingsListTile({
|
|
required this.icon,
|
|
required this.title,
|
|
required this.subtitle,
|
|
required this.onTap,
|
|
});
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return Card(
|
|
child: ListTile(
|
|
leading: Container(
|
|
padding: const EdgeInsets.all(8),
|
|
decoration: BoxDecoration(
|
|
color: kAccent.withValues(alpha: 0.15),
|
|
borderRadius: BorderRadius.circular(10),
|
|
),
|
|
child: Icon(icon, color: kAccent, size: 20),
|
|
),
|
|
title: Text(
|
|
title,
|
|
style: const TextStyle(fontSize: 14, fontWeight: FontWeight.w700),
|
|
),
|
|
subtitle: Text(
|
|
subtitle,
|
|
style: const TextStyle(fontSize: 12, color: kMuted),
|
|
maxLines: 1,
|
|
overflow: TextOverflow.ellipsis,
|
|
),
|
|
trailing: Icon(Icons.chevron_right_rounded, color: kMuted, size: 20),
|
|
onTap: onTap,
|
|
),
|
|
);
|
|
}
|
|
}
|