import 'dart:convert'; import 'package:flutter/material.dart'; import 'package:google_fonts/google_fonts.dart'; import 'package:http/http.dart' as http; import 'package:intl/intl.dart'; class EditPemeriksaanBalitaPage extends StatefulWidget { final Map data; const EditPemeriksaanBalitaPage({ super.key, required this.data, }); @override State createState() => _EditPemeriksaanBalitaPageState(); } class _EditPemeriksaanBalitaPageState extends State { final _formKey = GlobalKey(); final bbController = TextEditingController(); final tbController = TextEditingController(); final lkController = TextEditingController(); final catatanController = TextEditingController(); final tanggalController = TextEditingController(); String? vitaminA; String? pmt; bool _isSaving = false; DateTime selectedDate = DateTime.now(); // Variabel untuk Imunisasi List imunisasiList = []; Map selectedImunisasi = {}; bool loadingImunisasi = true; @override void initState() { super.initState(); // Load data awal dari widget.data String tglStr = widget.data["tanggal_pemeriksaan"] ?? ""; if (tglStr.isNotEmpty) { selectedDate = DateTime.tryParse(tglStr) ?? DateTime.now(); } tanggalController.text = DateFormat('dd-MM-yyyy').format(selectedDate); bbController.text = widget.data["bb"]?.toString() ?? ""; tbController.text = widget.data["tb"]?.toString() ?? ""; lkController.text = widget.data["lk"]?.toString() ?? ""; catatanController.text = widget.data["catatan"] ?? ""; vitaminA = widget.data["vitamin_a"]; pmt = widget.data["pmt"]; // Ambil data imunisasi ambilImunisasiOtomatis(); } Future ambilImunisasiOtomatis() async { try { final idBalita = widget.data["id_balita"]?.toString() ?? "0"; final response = await http.get( Uri.parse( "http://ta.myhost.id/E31230549/mposyandu_api/pemeriksaan_balita/get_imunisasi.php?id_balita=$idBalita"), ); if (response.statusCode == 200) { final data = json.decode(response.body); if (data["success"] == true) { imunisasiList = data["imunisasi"]; Map tempSelected = {}; for (var item in imunisasiList) { int id = int.parse(item["id"].toString()); tempSelected[id] = (item["checked"] == true || item["checked"] == 1 || item["checked"] == "true" || item["checked"] == "1"); } setState(() { selectedImunisasi = tempSelected; loadingImunisasi = false; }); } } } catch (e) { if (mounted) setState(() => loadingImunisasi = false); debugPrint("Error loading imunisasi: $e"); } } Future _pickDate() async { final picked = await showDatePicker( context: context, initialDate: selectedDate, firstDate: DateTime(2000), lastDate: DateTime(2100), ); if (picked != null) { setState(() { selectedDate = picked; tanggalController.text = DateFormat('dd-MM-yyyy').format(picked); }); } } Future _update() async { if (!_formKey.currentState!.validate()) return; setState(() => _isSaving = true); try { final url = Uri.parse( "http://ta.myhost.id/E31230549/mposyandu_api/pemeriksaan_balita/edit_pemeriksaan_balita.php"); // Format tanggal sesuai kebutuhan MySQL (YYYY-MM-DD) String formatTanggalDb = DateFormat('yyyy-MM-dd').format(selectedDate); // Gabungkan ID imunisasi yang dicentang menjadi string (contoh: "1,2,5") String imunisasiDipilih = selectedImunisasi.entries .where((e) => e.value == true) .map((e) => e.key.toString()) .join(","); // Kirim data menggunakan Map agar kompatibel dengan http.post body final response = await http.post(url, body: { "id_pemeriksaan": widget.data["id_pemeriksaan"].toString(), "tanggal_pemeriksaan": formatTanggalDb, "bb": bbController.text .replaceAll(',', '.') .trim(), // Bersihkan input desimal "tb": tbController.text.replaceAll(',', '.').trim(), "lk": lkController.text.replaceAll(',', '.').trim(), "vitamin_a": vitaminA ?? "", "pmt": pmt ?? "", "catatan": catatanController.text.trim(), "imunisasi": imunisasiDipilih }); final res = json.decode(response.body); if (res["success"] == true) { if (!mounted) return; ScaffoldMessenger.of(context).showSnackBar( const SnackBar( content: Text("Data berhasil diperbarui"), backgroundColor: Colors.green, ), ); Navigator.pop(context, true); // Kembali dengan nilai true untuk refresh data di halaman sebelumnya } else { throw res["message"] ?? "Gagal mengupdate data"; } } catch (e) { if (mounted) { ScaffoldMessenger.of(context).showSnackBar( SnackBar( content: Text("Gagal: $e"), backgroundColor: Colors.red, ), ); } } finally { if (mounted) setState(() => _isSaving = false); } } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( backgroundColor: Colors.blue, foregroundColor: Colors.white, elevation: 0, title: const Text(""), // Judul App Bar Kosong ), 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( crossAxisAlignment: CrossAxisAlignment.start, children: [ // Judul di pindahkan ke sini dan dibuat ke tengah Center( child: Text( "Edit Pemeriksaan Balita", style: GoogleFonts.poppins( fontSize: 18, fontWeight: FontWeight.bold, ), ), ), const SizedBox(height: 24), TextFormField( readOnly: true, onTap: _pickDate, controller: tanggalController, style: GoogleFonts.poppins(fontSize: 12), decoration: _decoration("Tanggal Pemeriksaan").copyWith( suffixIcon: const Icon(Icons.calendar_today, size: 16), ), validator: (v) => v == null || v.isEmpty ? "Wajib diisi" : null, ), const SizedBox(height: 16), _inputNumber(bbController, "Berat Badan (kg)"), const SizedBox(height: 16), _inputNumber(tbController, "Tinggi Badan (cm)"), const SizedBox(height: 16), _inputNumber(lkController, "Lingkar Kepala (cm)"), const SizedBox(height: 20), Text("Imunisasi Sesuai Usia", style: GoogleFonts.poppins( fontSize: 13, fontWeight: FontWeight.w600)), const SizedBox(height: 8), _buildCheckboxImunisasi(), const SizedBox(height: 16), _dropdown( label: "Vitamin A", hint: "Pilih Status", items: const ["Diberikan", "Belum"], value: vitaminA, onChanged: (v) => setState(() => vitaminA = v), ), const SizedBox(height: 16), _dropdown( label: "PMT", hint: "Pilih Status", items: const ["Diberikan", "Belum"], value: pmt, onChanged: (v) => setState(() => pmt = v), ), const SizedBox(height: 16), TextFormField( controller: catatanController, maxLines: 3, style: GoogleFonts.poppins(fontSize: 12), decoration: _decoration("Catatan (Opsional)"), ), const SizedBox(height: 28), SizedBox( width: double.infinity, height: 50, child: ElevatedButton( onPressed: _isSaving ? null : _update, style: ElevatedButton.styleFrom( backgroundColor: Colors.blue, foregroundColor: Colors.white, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(12), ), elevation: 2, ), child: _isSaving ? const SizedBox( width: 20, height: 20, child: CircularProgressIndicator( color: Colors.white, strokeWidth: 2)) : Text("Simpan Perubahan", style: GoogleFonts.poppins( fontWeight: FontWeight.bold)), ), ), ], ), ), ), ), ), ), ); } Widget _buildCheckboxImunisasi() { if (loadingImunisasi) { return const Padding( padding: EdgeInsets.symmetric(vertical: 10), child: Center(child: CircularProgressIndicator(strokeWidth: 2)), ); } if (imunisasiList.isEmpty) { return Text("Tidak ada daftar imunisasi", style: GoogleFonts.poppins(fontSize: 12, color: Colors.grey)); } return Column( children: imunisasiList.map((item) { final int id = int.parse(item["id"].toString()); return CheckboxListTile( value: selectedImunisasi[id] ?? false, onChanged: (bool? value) { setState(() { selectedImunisasi[id] = value ?? false; }); }, title: Text(item["nama_imunisasi"], style: GoogleFonts.poppins(fontSize: 12)), controlAffinity: ListTileControlAffinity.leading, contentPadding: EdgeInsets.zero, dense: true, activeColor: Colors.blue, ); }).toList(), ); } Widget _inputNumber(TextEditingController controller, String label) { return TextFormField( controller: controller, keyboardType: const TextInputType.numberWithOptions(decimal: true), style: GoogleFonts.poppins(fontSize: 12), decoration: _decoration("$label (Opsional)"), ); } Widget _dropdown({ required String label, required String hint, required List items, required String? value, required Function(String?) onChanged, }) { return DropdownButtonFormField( value: (value == null || value.isEmpty) ? null : value, hint: Text(hint, style: GoogleFonts.poppins(fontSize: 12)), style: GoogleFonts.poppins(fontSize: 12, color: Colors.black), items: items.map((e) => DropdownMenuItem(value: e, child: Text(e))).toList(), onChanged: onChanged, decoration: _decoration(label), ); } InputDecoration _decoration(String label) { return InputDecoration( filled: true, fillColor: Colors.white, labelText: label, labelStyle: GoogleFonts.poppins(fontSize: 12), border: OutlineInputBorder(borderRadius: BorderRadius.circular(12)), enabledBorder: OutlineInputBorder( borderRadius: BorderRadius.circular(12), borderSide: const BorderSide(color: Colors.black12), ), focusedBorder: OutlineInputBorder( borderRadius: BorderRadius.circular(12), borderSide: const BorderSide(color: Colors.blue, width: 2), ), contentPadding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12), ); } @override void dispose() { bbController.dispose(); tbController.dispose(); lkController.dispose(); catatanController.dispose(); tanggalController.dispose(); super.dispose(); } }