import 'package:flutter/material.dart'; import 'package:get/get.dart'; import 'numpad_nominal_widget.dart'; class AmbilUangModal extends StatefulWidget { final int saldoSaatIni; final void Function(int jumlah) onAmbil; const AmbilUangModal({ super.key, required this.saldoSaatIni, required this.onAmbil, }); static void show( BuildContext context, { required int saldoSaatIni, required void Function(int jumlah) onAmbil, }) { showModalBottomSheet( context: context, backgroundColor: Colors.white, isScrollControlled: true, isDismissible: false, enableDrag: false, shape: const RoundedRectangleBorder( borderRadius: BorderRadius.vertical(top: Radius.circular(24)), ), builder: (_) => AmbilUangModal(saldoSaatIni: saldoSaatIni, onAmbil: onAmbil), ); } @override State createState() => _AmbilUangModalState(); } class _AmbilUangModalState extends State { final _nominalController = TextEditingController(); bool _ambilSemua = false; String _errorMessage = ''; final _currencyFormat = RegExp(r'\B(?=(\d{3})+(?!\d))'); String _formatRupiah(int value) { return 'Rp ${value.toString().replaceAllMapped(_currencyFormat, (m) => '.')}'; } int get _parsedNominal { final raw = _nominalController.text.replaceAll(RegExp(r'[^0-9]'), ''); return int.tryParse(raw) ?? 0; } void _onNominalKey(String key) { setState(() { _ambilSemua = false; _errorMessage = ''; }); if (key == 'del') { if (_nominalController.text.isNotEmpty) { _nominalController.text = _nominalController.text.substring( 0, _nominalController.text.length - 1, ); } } else { _nominalController.text += key; } } void _pilihAmbilSemua() { setState(() { _ambilSemua = true; _errorMessage = ''; _nominalController.text = widget.saldoSaatIni.toString(); }); } void _konfirmasi() { final jumlah = _ambilSemua ? widget.saldoSaatIni : _parsedNominal; if (jumlah <= 0) { setState(() => _errorMessage = 'Masukkan jumlah yang ingin diambil'); return; } if (jumlah > widget.saldoSaatIni) { setState( () => _errorMessage = 'Jumlah melebihi saldo (${_formatRupiah(widget.saldoSaatIni)})', ); return; } Navigator.of(context).pop(); widget.onAmbil(jumlah); } @override void dispose() { _nominalController.dispose(); super.dispose(); } @override Widget build(BuildContext context) { return Padding( padding: EdgeInsets.fromLTRB( 24, 16, 24, MediaQuery.of(context).viewInsets.bottom + 32, ), child: Column( mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.start, children: [ // Handle bar Center( child: Container( width: 40, height: 4, margin: const EdgeInsets.only(bottom: 20), decoration: BoxDecoration( color: Colors.grey.shade300, borderRadius: BorderRadius.circular(2), ), ), ), const Center( child: Text( '🎉 Celengan Dibuka!', style: TextStyle( fontSize: 20, fontWeight: FontWeight.bold, color: Colors.black87, ), ), ), const SizedBox(height: 6), Center( child: Text( 'Mau ambil berapa?', style: TextStyle(fontSize: 14, color: Colors.grey.shade600), ), ), const SizedBox(height: 20), // Info saldo Container( width: double.infinity, padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12), decoration: BoxDecoration( color: const Color(0xFFEAF4FC), borderRadius: BorderRadius.circular(12), ), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ const Text( 'Saldo Celengan', style: TextStyle(fontSize: 13, color: Colors.black54), ), Text( _formatRupiah(widget.saldoSaatIni), style: const TextStyle( fontSize: 15, fontWeight: FontWeight.bold, color: Color(0xFF5B9BD5), ), ), ], ), ), const SizedBox(height: 16), // Input nominal const Text( 'Jumlah yang diambil', style: TextStyle( fontSize: 13, fontWeight: FontWeight.w600, color: Colors.black54, ), ), const SizedBox(height: 8), GestureDetector( onTap: () => NumpadNominalWidget.show( context, controller: _nominalController, onKey: _onNominalKey, onSimpan: () => Get.back(), ), child: Container( width: double.infinity, padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 16), decoration: BoxDecoration( color: const Color(0xFFF2F2F2), borderRadius: BorderRadius.circular(12), border: _errorMessage.isNotEmpty ? Border.all(color: Colors.red.shade300) : null, ), child: Row( children: [ const Icon( Icons.attach_money_outlined, color: Colors.grey, size: 20, ), const SizedBox(width: 12), Expanded( child: ValueListenableBuilder( valueListenable: _nominalController, builder: (_, value, __) { final raw = value.text.replaceAll( RegExp(r'[^0-9]'), '', ); final display = raw.isEmpty ? 'Masukkan nominal' : _formatRupiah(int.tryParse(raw) ?? 0); return Text( display, style: TextStyle( fontSize: 14, color: raw.isEmpty ? Colors.grey : Colors.black87, ), ); }, ), ), ], ), ), ), // Error message if (_errorMessage.isNotEmpty) Padding( padding: const EdgeInsets.only(top: 6), child: Text( _errorMessage, style: TextStyle(color: Colors.red.shade600, fontSize: 12), ), ), const SizedBox(height: 12), // Shortcut: Ambil Semua GestureDetector( onTap: _pilihAmbilSemua, child: AnimatedContainer( duration: const Duration(milliseconds: 200), width: double.infinity, padding: const EdgeInsets.symmetric(vertical: 14), decoration: BoxDecoration( color: _ambilSemua ? const Color(0xFF5B9BD5).withOpacity(0.12) : Colors.grey.shade100, borderRadius: BorderRadius.circular(12), border: Border.all( color: _ambilSemua ? const Color(0xFF5B9BD5) : Colors.grey.shade300, width: _ambilSemua ? 1.5 : 1, ), ), child: Row( mainAxisAlignment: MainAxisAlignment.center, children: [ Icon( Icons.select_all_rounded, size: 18, color: _ambilSemua ? const Color(0xFF5B9BD5) : Colors.grey.shade600, ), const SizedBox(width: 8), Text( 'Ambil Semua (${_formatRupiah(widget.saldoSaatIni)})', style: TextStyle( fontSize: 14, fontWeight: FontWeight.w600, color: _ambilSemua ? const Color(0xFF5B9BD5) : Colors.grey.shade600, ), ), ], ), ), ), const SizedBox(height: 20), // Tombol Ambil GestureDetector( onTap: _konfirmasi, child: Container( width: double.infinity, padding: const EdgeInsets.symmetric(vertical: 16), decoration: BoxDecoration( color: const Color(0xFF5B9BD5), borderRadius: BorderRadius.circular(12), ), child: const Center( child: Text( 'Ambil Uang', style: TextStyle( color: Colors.white, fontWeight: FontWeight.bold, fontSize: 16, ), ), ), ), ), ], ), ); } }