MIF_E31230549/lib/kader/crud_balita/edit_balita.dart

456 lines
16 KiB
Dart

import 'dart:convert';
import 'dart:developer';
import 'package:flutter/material.dart';
import 'package:google_fonts/google_fonts.dart';
import 'package:http/http.dart' as http;
import 'package:shared_preferences/shared_preferences.dart';
class EditBalitaPage extends StatefulWidget {
final Map<String, dynamic> data;
const EditBalitaPage({super.key, required this.data});
@override
State<EditBalitaPage> createState() => _EditBalitaPageState();
}
class _EditBalitaPageState extends State<EditBalitaPage> {
final _formKey = GlobalKey<FormState>();
final namaC = TextEditingController();
final nikC = TextEditingController();
final tglLahirC = TextEditingController();
final usiaC = TextEditingController();
final tempatLahirC = TextEditingController();
final anakKeC = TextEditingController();
final beratC = TextEditingController();
final panjangC = TextEditingController();
final tglDaftarC = TextEditingController();
bool _isSaving = false;
bool _isLoadingIbu = true;
List ibuList = [];
String? selectedIbuId;
String? selectedJK;
// Tambahkan Variabel Status
String? selectedStatus;
int usiaBulan = 0;
@override
void initState() {
super.initState();
namaC.text = widget.data["nama"] ?? "";
nikC.text = widget.data["nik_balita"] ?? "";
tglLahirC.text = widget.data["tanggal_lahir"] ?? "";
tempatLahirC.text = widget.data["tempat_lahir"] ?? "";
anakKeC.text = widget.data["anak_ke"]?.toString() ?? "";
beratC.text = widget.data["berat_lahir"]?.toString() ?? "";
panjangC.text = widget.data["panjang_lahir"]?.toString() ?? "";
tglDaftarC.text = widget.data["tanggal_daftar"] ?? "";
selectedIbuId = widget.data["ibu_id"]?.toString();
selectedJK = widget.data["jenis_kelamin"];
// Inisialisasi Status dari data yang diterima
selectedStatus = widget.data["status"]?.toString().toLowerCase();
if (tglLahirC.text.isNotEmpty) {
try {
DateTime tgl = DateTime.parse(tglLahirC.text);
_hitungUsia(tgl);
} catch (e) {
usiaBulan = int.tryParse(widget.data["usia"]?.toString() ?? "0") ?? 0;
_setUsiaText();
}
} else {
usiaBulan = int.tryParse(widget.data["usia"]?.toString() ?? "0") ?? 0;
_setUsiaText();
}
_loadIbu();
}
@override
void dispose() {
namaC.dispose();
nikC.dispose();
tglLahirC.dispose();
usiaC.dispose();
tempatLahirC.dispose();
anakKeC.dispose();
beratC.dispose();
panjangC.dispose();
tglDaftarC.dispose();
super.dispose();
}
Future<void> _loadIbu() async {
try {
final prefs = await SharedPreferences.getInstance();
final String? role = prefs.getString("role");
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) {
List allIbu = data["data"] ?? [];
if (mounted) {
setState(() {
if (role == 'kader' && userDusunId != "" && userDusunId != "0") {
ibuList = allIbu.where((ibu) {
return ibu["dusun_id"].toString() == userDusunId;
}).toList();
bool exists =
ibuList.any((e) => e["id"].toString() == selectedIbuId);
if (!exists) {
var currentIbu = allIbu.firstWhere(
(e) => e["id"].toString() == selectedIbuId,
orElse: () => null);
if (currentIbu != null) {
ibuList.add(currentIbu);
} else {
ibuList.add({
"id": selectedIbuId,
"label": widget.data["nama_ibu"] ?? "Ibu Saat Ini"
});
}
}
} else {
ibuList = allIbu;
}
_isLoadingIbu = false;
});
}
}
} catch (e) {
log("Error load ibu: $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) {
bulan--;
final prevMonth = DateTime(now.year, now.month, 0);
hari += prevMonth.day;
}
if (bulan < 0) {
tahun--;
bulan += 12;
}
usiaBulan = (tahun * 12) + bulan;
_setUsiaText(tahun, bulan, hari);
}
void _setUsiaText([int? tahun, int? bulan, int? hari]) {
if (tahun == null || bulan == null) {
tahun = usiaBulan ~/ 12;
bulan = usiaBulan % 12;
hari = 0;
}
usiaC.text = "$tahun tahun $bulan bulan $hari hari";
}
Future<void> _pickDate(TextEditingController controller) async {
DateTime initialDate = DateTime.now();
if (controller.text.isNotEmpty) {
try {
initialDate = DateTime.parse(controller.text);
} catch (_) {}
}
final picked = await showDatePicker(
context: context,
firstDate: DateTime(2000),
lastDate: DateTime.now(),
initialDate: initialDate,
);
if (picked != null) {
setState(() {
controller.text = picked.toIso8601String().split("T").first;
if (controller == tglLahirC) {
_hitungUsia(picked);
}
});
}
}
Future<void> _update() async {
if (!_formKey.currentState!.validate()) return;
if (selectedIbuId == null || selectedJK == null || selectedStatus == null) {
_showSnackBar("Lengkapi data wajib terlebih dahulu");
return;
}
setState(() => _isSaving = true);
try {
final response = await http.post(
Uri.parse(
"http://ta.myhost.id/E31230549/mposyandu_api/balita/edit_balita.php"),
body: {
"id": widget.data["id"].toString(),
"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!, // Kirim status ke API
},
);
log("Response: ${response.body}");
final data = json.decode(response.body);
if (data["success"] == true) {
if (!mounted) return;
_showSnackBar("Data berhasil diupdate");
Navigator.pop(context, true);
} else {
_showSnackBar(data["message"] ?? "Gagal update");
}
} catch (e) {
log("Error update: $e");
_showSnackBar("Terjadi kesalahan koneksi");
} finally {
if (mounted) setState(() => _isSaving = false);
}
}
void _showSnackBar(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(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Text(
"Edit Data Balita",
textAlign: TextAlign.center,
style: GoogleFonts.poppins(
fontSize: 18,
fontWeight: FontWeight.bold,
color: Colors.black87,
),
),
const SizedBox(height: 24),
_isLoadingIbu
? const Center(child: CircularProgressIndicator())
: DropdownButtonFormField<String>(
isExpanded: true,
value: selectedIbuId,
style: GoogleFonts.poppins(
fontSize: 12, color: Colors.black),
decoration: _decoration("Pilih Ibu (Orang Tua)"),
items: ibuList.map((item) {
return DropdownMenuItem<String>(
value: item["id"].toString(),
child: Text(item["label"] ?? item["nama"] ?? "",
overflow: TextOverflow.ellipsis,
style: GoogleFonts.poppins(fontSize: 12)),
);
}).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),
DropdownButtonFormField<String>(
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 ? "Pilih jenis kelamin" : null,
),
const SizedBox(height: 16),
_input("Tempat Lahir", tempatLahirC, isOptional: true),
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, color: Colors.black),
),
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, isOptional: true),
_input("Berat Lahir (kg)", beratC,
keyboard: const TextInputType.numberWithOptions(
decimal: true),
isOptional: true),
_input("Panjang Lahir (cm)", panjangC,
keyboard: const TextInputType.numberWithOptions(
decimal: true),
isOptional: true),
// DROPDOWN STATUS BARU
DropdownButtonFormField<String>(
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),
validator: (v) => v == null ? "Pilih status" : null,
),
const SizedBox(height: 16),
TextFormField(
controller: tglDaftarC,
readOnly: true,
style: GoogleFonts.poppins(fontSize: 12),
onTap: () => _pickDate(tglDaftarC),
decoration: _decoration("Tanggal Daftar").copyWith(
suffixIcon: const Icon(Icons.calendar_today,
size: 18, color: Colors.black),
),
validator: (v) =>
(v == null || v.isEmpty) ? "Wajib diisi" : null,
),
const SizedBox(height: 28),
SizedBox(
height: 50,
child: OutlinedButton(
onPressed: _isSaving ? null : _update,
style: OutlinedButton.styleFrom(
side: const BorderSide(
color: Colors.blueAccent, width: 2),
shape: const StadiumBorder(),
),
child: _isSaving
? const Center(
child: SizedBox(
width: 20,
height: 20,
child: CircularProgressIndicator(
strokeWidth: 2,
color: Colors.blueAccent)))
: Text("Simpan Perubahan",
style: GoogleFonts.poppins(
fontWeight: FontWeight.bold,
fontSize: 14,
color: Colors.blueAccent)),
),
)
],
),
),
),
),
),
),
);
}
Widget _input(String label, TextEditingController c,
{TextInputType keyboard = TextInputType.text, bool isOptional = false}) {
return Padding(
padding: const EdgeInsets.only(bottom: 16),
child: TextFormField(
controller: c,
keyboardType: keyboard,
style: GoogleFonts.poppins(fontSize: 12),
decoration: _decoration(label),
validator: (v) {
if (isOptional) return null;
return (v == null || v.trim().isEmpty) ? "$label wajib diisi" : 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),
);
}
}