import 'dart:convert'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:google_fonts/google_fonts.dart'; import 'package:http/http.dart' as http; import 'package:shared_preferences/shared_preferences.dart'; class TambahBalitaPage extends StatefulWidget { const TambahBalitaPage({super.key}); @override State createState() => _TambahBalitaPageState(); } class _TambahBalitaPageState extends State { final _formKey = GlobalKey(); final namaC = TextEditingController(); final nikC = TextEditingController(); final tglLahirC = TextEditingController(); final tempatLahirC = TextEditingController(); final anakKeC = TextEditingController(); final beratC = TextEditingController(); final panjangC = TextEditingController(); final tglDaftarC = TextEditingController(); final usiaC = TextEditingController(); bool _isSaving = false; bool _isLoadingIbu = true; List ibuList = []; String? selectedIbuId; String? selectedJK; // Tambahkan Variabel Status String selectedStatus = "belum lolos"; // Default sesuai DB @override void initState() { super.initState(); tglDaftarC.text = DateTime.now().toIso8601String().split("T").first; _loadIbu(); } @override void dispose() { namaC.dispose(); nikC.dispose(); tglLahirC.dispose(); tempatLahirC.dispose(); anakKeC.dispose(); beratC.dispose(); panjangC.dispose(); tglDaftarC.dispose(); usiaC.dispose(); super.dispose(); } Future _loadIbu() async { try { final prefs = await SharedPreferences.getInstance(); final dynamic rawDusunId = prefs.get("dusun_id"); final String userDusunId = rawDusunId?.toString() ?? ""; final res = await http.get( Uri.parse( "http://ta.myhost.id/E31230549/mposyandu_api/ibu/get_ibu_dropdown.php?dusun_id=$userDusunId"), ); final data = json.decode(res.body); if (data["success"] == true) { setState(() { ibuList = data["data"] ?? []; _isLoadingIbu = false; }); } else { if (mounted) setState(() => _isLoadingIbu = false); } } catch (e) { if (mounted) setState(() => _isLoadingIbu = false); } } void _hitungUsia(DateTime tgl) { final now = DateTime.now(); int tahun = now.year - tgl.year; int bulan = now.month - tgl.month; int hari = now.day - tgl.day; if (hari < 0) { final prevMonth = DateTime(now.year, now.month, 0); hari += prevMonth.day; bulan--; } if (bulan < 0) { bulan += 12; tahun--; } usiaC.text = "$tahun tahun $bulan bulan $hari hari"; } Future _pickDate(TextEditingController controller) async { final picked = await showDatePicker( context: context, firstDate: DateTime(2000), lastDate: DateTime.now(), initialDate: DateTime.now(), ); if (picked != null) { setState(() { controller.text = picked.toIso8601String().split("T").first; if (controller == tglLahirC) { _hitungUsia(picked); } }); } } Future _simpan() async { if (!_formKey.currentState!.validate()) return; if (selectedIbuId == null) { _showMsg("Pilih ibu terlebih dahulu"); return; } if (selectedJK == null) { _showMsg("Pilih jenis kelamin"); return; } setState(() => _isSaving = true); try { final url = Uri.parse( "http://ta.myhost.id/E31230549/mposyandu_api/balita/tambah_balita.php"); final response = await http.post(url, body: { "ibu_id": selectedIbuId!, "nama": namaC.text.trim(), "nik_balita": nikC.text.trim(), "jenis_kelamin": selectedJK!, "tanggal_lahir": tglLahirC.text.trim(), "tempat_lahir": tempatLahirC.text.trim(), "anak_ke": anakKeC.text.trim(), "berat_lahir": beratC.text.trim(), "panjang_lahir": panjangC.text.trim(), "tanggal_daftar": tglDaftarC.text.trim(), "status": selectedStatus, // Mengirim status ke API }); final data = json.decode(response.body); if (data["success"] == true) { _showMsg("Data balita berhasil disimpan"); if (mounted) Navigator.pop(context, true); } else { _showMsg(data["message"] ?? "Gagal simpan"); } } catch (e) { _showMsg("Gagal koneksi server"); } finally { if (mounted) setState(() => _isSaving = false); } } void _showMsg(String msg) { ScaffoldMessenger.of(context).showSnackBar( SnackBar(content: Text(msg, style: GoogleFonts.poppins(fontSize: 12))), ); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( backgroundColor: Colors.blue, foregroundColor: Colors.white, title: Text("", style: GoogleFonts.poppins(fontSize: 14, fontWeight: FontWeight.w600)), ), backgroundColor: const Color(0xfff4f6fb), body: Center( child: SingleChildScrollView( padding: const EdgeInsets.all(16), child: ConstrainedBox( constraints: const BoxConstraints(maxWidth: 420), child: Container( padding: const EdgeInsets.all(24), decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(20), boxShadow: const [ BoxShadow( blurRadius: 16, color: Colors.black12, offset: Offset(0, 8)) ], ), child: Form( key: _formKey, child: Column( children: [ Text("Tambah Data Balita", style: GoogleFonts.poppins( fontSize: 18, fontWeight: FontWeight.bold)), const SizedBox(height: 24), _isLoadingIbu ? const Center(child: CircularProgressIndicator()) : DropdownButtonFormField( isExpanded: true, value: selectedIbuId, style: GoogleFonts.poppins( fontSize: 12, color: Colors.black), decoration: _decoration("Pilih Ibu (Orang Tua)"), items: ibuList.map((item) { return DropdownMenuItem( value: item["id"].toString(), child: Text( "${item["nama"]} (${item["nama_suami"] ?? '-'})", overflow: TextOverflow.ellipsis), ); }).toList(), onChanged: (v) => setState(() => selectedIbuId = v), validator: (v) => v == null ? "Ibu wajib dipilih" : null, ), const SizedBox(height: 16), _input("Nama Lengkap Balita", namaC), _input("NIK Balita", nikC, keyboard: TextInputType.number, isNik: true), DropdownButtonFormField( value: selectedJK, style: GoogleFonts.poppins( fontSize: 12, color: Colors.black), decoration: _decoration("Jenis Kelamin"), items: const [ DropdownMenuItem(value: "L", child: Text("Laki-laki")), DropdownMenuItem(value: "P", child: Text("Perempuan")), ], onChanged: (v) => setState(() => selectedJK = v), validator: (v) => v == null ? "Wajib dipilih" : null, ), const SizedBox(height: 16), _input("Tempat Lahir", tempatLahirC), TextFormField( controller: tglLahirC, readOnly: true, style: GoogleFonts.poppins(fontSize: 12), onTap: () => _pickDate(tglLahirC), decoration: _decoration("Tanggal Lahir").copyWith( suffixIcon: const Icon(Icons.calendar_today, size: 18), ), validator: (v) => v == null || v.isEmpty ? "Wajib diisi" : null, ), const SizedBox(height: 16), TextFormField( controller: usiaC, readOnly: true, style: GoogleFonts.poppins(fontSize: 12), decoration: _decoration("Usia (Otomatis)"), ), const SizedBox(height: 16), _input("Anak Ke-", anakKeC, keyboard: TextInputType.number), _input("Berat Lahir (kg)", beratC, keyboard: TextInputType.number), _input("Panjang Lahir (cm)", panjangC, keyboard: TextInputType.number), // DROPDOWN STATUS BARU DropdownButtonFormField( value: selectedStatus, style: GoogleFonts.poppins( fontSize: 12, color: Colors.black), decoration: _decoration("Status Seleksi"), items: const [ DropdownMenuItem( value: "belum lolos", child: Text("Belum Lolos")), DropdownMenuItem(value: "lolos", child: Text("Lolos")), ], onChanged: (v) => setState(() => selectedStatus = v!), ), const SizedBox(height: 16), TextFormField( controller: tglDaftarC, readOnly: true, style: GoogleFonts.poppins(fontSize: 12), onTap: () => _pickDate(tglDaftarC), decoration: _decoration("Tanggal Pendaftaran").copyWith( suffixIcon: const Icon(Icons.calendar_today, size: 18), ), ), const SizedBox(height: 28), SizedBox( width: double.infinity, height: 50, child: OutlinedButton( onPressed: _isSaving ? null : _simpan, style: OutlinedButton.styleFrom( side: const BorderSide( color: Colors.blueAccent, width: 1.5), shape: const StadiumBorder(), ), child: _isSaving ? const SizedBox( height: 20, width: 20, child: CircularProgressIndicator(strokeWidth: 2)) : Text("Simpan Data Balita", style: GoogleFonts.poppins( fontWeight: FontWeight.bold, color: Colors.blueAccent)), ), ), ], ), ), ), ), ), ), ); } Widget _input(String label, TextEditingController c, {TextInputType keyboard = TextInputType.text, bool isNik = false}) { return Padding( padding: const EdgeInsets.only(bottom: 16), child: TextFormField( controller: c, keyboardType: keyboard, inputFormatters: isNik ? [ FilteringTextInputFormatter.digitsOnly, LengthLimitingTextInputFormatter(16) ] : null, style: GoogleFonts.poppins(fontSize: 12), decoration: _decoration(label), validator: (v) { if (![ "Tempat Lahir", "Anak Ke-", "Berat Lahir (kg)", "Panjang Lahir (cm)" ].contains(label)) { if (v == null || v.isEmpty) return "$label wajib"; } if (isNik && v != null && v.isNotEmpty && v.length != 16) return "Harus 16 digit"; return null; }, ), ); } InputDecoration _decoration(String label) { return InputDecoration( filled: true, fillColor: Colors.white, labelText: label, labelStyle: GoogleFonts.poppins(fontSize: 12), border: OutlineInputBorder(borderRadius: BorderRadius.circular(12)), contentPadding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12), ); } }