import 'dart:io'; import 'package:flutter/material.dart'; import 'package:dio/dio.dart'; import 'package:file_picker/file_picker.dart'; import 'package:monitoring/config.dart'; class TambahPembayaranScreen extends StatefulWidget { final String token; const TambahPembayaranScreen({super.key, required this.token}); @override State createState() => _TambahPembayaranScreenState(); } class _TambahPembayaranScreenState extends State { final formKey = GlobalKey(); String jenis = 'SPP'; String tanggal = ''; int jumlah = 0; String keterangan = ''; File? bukti; bool isLoading = false; Future submit() async { if (!formKey.currentState!.validate()) return; if (bukti == null) { ScaffoldMessenger.of( context, ).showSnackBar(const SnackBar(content: Text('Bukti belum dipilih'))); return; } setState(() => isLoading = true); final dio = Dio( BaseOptions( baseUrl: '$baseUrl', headers: { 'Accept': 'application/json', 'Authorization': 'Bearer ${widget.token}', }, ), ); final formData = FormData.fromMap({ 'tanggal': tanggal, 'jenis_pembayaran': jenis, 'jumlah': jumlah, 'keterangan': keterangan, 'bukti_pembayaran': await MultipartFile.fromFile(bukti!.path), }); try { final response = await dio.post('/pembayaran', data: formData); if (response.statusCode == 201) { ScaffoldMessenger.of(context).showSnackBar( const SnackBar(content: Text('Pembayaran berhasil dikirim')), ); Navigator.pop(context); } else { ScaffoldMessenger.of(context).showSnackBar( const SnackBar(content: Text('Gagal mengirim pembayaran')), ); } } catch (e) { debugPrint('Gagal kirim pembayaran: $e'); ScaffoldMessenger.of( context, ).showSnackBar(SnackBar(content: Text('Terjadi kesalahan: $e'))); } finally { setState(() => isLoading = false); // selesai loading } } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: const Text('Tambah Pembayaran')), body: Padding( padding: const EdgeInsets.all(16), child: Form( key: formKey, child: ListView( children: [ DropdownButtonFormField( value: jenis, items: const [ DropdownMenuItem(value: 'SPP', child: Text('SPP')), DropdownMenuItem( value: 'Uang Makan', child: Text('Uang Makan'), ), DropdownMenuItem( value: 'Uang Asrama', child: Text('Uang Asrama'), ), DropdownMenuItem( value: 'Uang Kegiatan', child: Text('Uang Kegiatan'), ), DropdownMenuItem( value: 'Uang Seragam', child: Text('Uang Seragam'), ), DropdownMenuItem(value: 'Lainnya', child: Text('Lainnya')), ], onChanged: (val) => setState(() => jenis = val!), decoration: const InputDecoration( labelText: 'Jenis Pembayaran', ), ), const SizedBox(height: 12), TextFormField( decoration: const InputDecoration(labelText: 'Jumlah'), keyboardType: TextInputType.number, onChanged: (val) => jumlah = int.tryParse(val) ?? 0, validator: (val) => val == null || val.isEmpty ? 'Jumlah wajib diisi' : null, ), const SizedBox(height: 12), TextFormField( decoration: const InputDecoration(labelText: 'Tanggal'), controller: TextEditingController(text: tanggal), readOnly: true, onTap: () async { final picked = await showDatePicker( context: context, initialDate: DateTime.now(), firstDate: DateTime(2022), lastDate: DateTime(2030), ); if (picked != null) { setState(() { tanggal = picked.toIso8601String().split('T')[0]; }); } }, validator: (val) => val == null || val.isEmpty ? 'Tanggal wajib diisi' : null, ), const SizedBox(height: 12), TextFormField( decoration: const InputDecoration(labelText: 'Keterangan'), maxLines: 2, onChanged: (val) => keterangan = val, ), const SizedBox(height: 12), ElevatedButton.icon( onPressed: () async { final picked = await FilePicker.platform.pickFiles( type: FileType.image, ); if (picked != null && picked.files.first.path != null) { setState(() { bukti = File(picked.files.first.path!); }); } }, icon: const Icon(Icons.attach_file), label: const Text('Pilih Bukti Pembayaran'), ), if (bukti != null) ...[ const SizedBox(height: 10), const Text( 'Preview Bukti:', style: TextStyle(fontWeight: FontWeight.bold), ), const SizedBox(height: 8), ClipRRect( borderRadius: BorderRadius.circular(8), child: Image.file( bukti!, height: 200, width: double.infinity, fit: BoxFit.cover, ), ), ], const SizedBox(height: 24), ElevatedButton.icon( onPressed: isLoading ? null : submit, icon: isLoading ? const SizedBox( height: 20, width: 20, child: CircularProgressIndicator( strokeWidth: 2, color: Colors.white, ), ) : const Icon(Icons.save), label: Text(isLoading ? 'Proses...' : 'Kirim Pembayaran'), style: ElevatedButton.styleFrom( backgroundColor: Colors.teal, padding: const EdgeInsets.symmetric(vertical: 14), ), ), ], ), ), ), ); } }