import 'package:flutter/material.dart'; import 'package:frontend/api_services/api_services.dart'; import 'package:http/http.dart' as http; class EditRulePage extends StatefulWidget { @override _EditRulePageState createState() => _EditRulePageState(); final bool isEditing; final bool isEditingHama; final List selectedRuleIds; final List selectedGejalaIds; final List nilaiPakarList; final int? selectedHamaId; final int? selectedPenyakitId; final bool showHamaOnly; // Tambahkan ini final bool showPenyakitOnly; // Tambahkan ini const EditRulePage({ Key? key, required this.isEditing, required this.isEditingHama, required this.selectedRuleIds, required this.selectedGejalaIds, required this.nilaiPakarList, this.showHamaOnly = false, // Tambahkan default value this.showPenyakitOnly = false, this.selectedHamaId, this.selectedPenyakitId, }) : super(key: key); } class _EditRulePageState extends State { int? selectedHamaId; int? selectedPenyakitId; List selectedGejalaIds = [null]; List nilaiPakarList = [0.5]; List selectedRuleIds = []; bool isEditing = true; // atau false jika sedang edit penyakit bool isLoading = true; bool showHamaOnly = false; bool showPenyakitOnly = false; final api = ApiService(); // Deklarasi variabel untuk menampung data dari API List> hamaList = []; List> penyakitList = []; List> gejalaList = []; void loadRulesForEditing() async { try { final fetchedRules = isEditing ? await api.getRulesHama() : await api.getRulesPenyakit(); print('Fetched Rules: $fetchedRules'); // Filter data yang valid dan konversi dengan aman final validRules = fetchedRules.where((rule) { if (rule is Map) { // Pastikan semua key yang diperlukan ada dan nilainya tidak null return rule.containsKey('id') && rule.containsKey('id_gejala') && rule.containsKey('nilai_pakar') && (rule.containsKey('id_penyakit') || rule.containsKey('id_hama')) && rule['id'] != null && rule['id_gejala'] != null && rule['nilai_pakar'] != null && (rule['id_penyakit'] != null || rule['id_hama'] != null); } return false; }).toList(); // Pastikan konversi tipe data dilakukan dengan aman setState(() { selectedRuleIds = validRules.map((rule) { // Pastikan id bisa dikonversi ke int final id = rule['id']; return id is int ? id : (id is String ? int.tryParse(id) : null); }).toList(); selectedGejalaIds = validRules.map((rule) { // Pastikan id_gejala bisa dikonversi ke int final idGejala = rule['id_gejala']; return idGejala is int ? idGejala : (idGejala is String ? int.tryParse(idGejala) : null); }).toList(); nilaiPakarList = validRules.map((rule) { // Pastikan nilai_pakar bisa dikonversi ke double final nilaiPakar = rule['nilai_pakar']; if (nilaiPakar is double) return nilaiPakar; if (nilaiPakar is int) return nilaiPakar.toDouble(); if (nilaiPakar is String) return double.tryParse(nilaiPakar) ?? 0.5; return 0.5; // Nilai default }).toList(); print('Valid Rules: $validRules'); print('selectedRuleIds: $selectedRuleIds'); print('selectedGejalaIds: $selectedGejalaIds'); print('nilaiPakarList: $nilaiPakarList'); }); } catch (e) { print("Gagal memuat data rule: $e"); ScaffoldMessenger.of( context, ).showSnackBar(SnackBar(content: Text("Gagal memuat data rule: $e"))); } } // Fungsi untuk fetch data dari API Future fetchData() async { setState(() { isLoading = true; // Mengatur status loading saat mulai ambil data }); try { // Ambil data dari API final hamaData = await api.getHama(); final penyakitData = await api.getPenyakit(); final gejalaData = await api.getGejala(); // Debugging: Cek apakah data yang diterima dari API print("Hama Data: $hamaData"); print("Penyakit Data: $penyakitData"); print("Gejala Data: $gejalaData"); // Pengecekan jika data kosong if (hamaData.isEmpty || penyakitData.isEmpty || gejalaData.isEmpty) { print("Data kosong, periksa API atau koneksi."); } // Update data dan status loading setState(() { hamaList = hamaData; penyakitList = penyakitData; gejalaList = gejalaData; isLoading = false; // Mengubah status loading setelah data diterima }); } catch (e) { // Menangani error jika fetch gagal print("Error fetching data: $e"); setState(() { isLoading = false; // Mengubah status loading selesai meskipun terjadi error }); } } @override void initState() { super.initState(); showHamaOnly = widget.showHamaOnly; showPenyakitOnly = widget.showPenyakitOnly; fetchData(); // Panggil fetchData saat halaman dibuka pertama kali // Inisialisasi dari widget parent if (widget.isEditing) { selectedHamaId = widget.selectedHamaId; selectedPenyakitId = widget.selectedPenyakitId; // Copy nilai dari widget ke state if (widget.selectedRuleIds.isNotEmpty) { selectedRuleIds = List.from(widget.selectedRuleIds); } if (widget.selectedGejalaIds.isNotEmpty) { selectedGejalaIds = List.from(widget.selectedGejalaIds); } if (widget.nilaiPakarList.isNotEmpty) { nilaiPakarList = List.from(widget.nilaiPakarList); } } } void updateRules() async { if (selectedRuleIds.length != selectedGejalaIds.length || selectedRuleIds.length != nilaiPakarList.length) { ScaffoldMessenger.of(context).showSnackBar( SnackBar( content: Text("Data rule tidak sinkron. Silakan cek kembali."), ), ); return; } try { for (int i = 0; i < selectedGejalaIds.length; i++) { final idRule = selectedRuleIds[i]; final idGejala = selectedGejalaIds[i]; final nilai = nilaiPakarList[i]; if (idRule == null || idGejala == null) { print("Lewat karena data null pada index ke-$i"); continue; } http.Response response; if (selectedPenyakitId != null) { response = await ApiService.updateRulePenyakit( id: idRule, idGejala: idGejala, idPenyakit: selectedPenyakitId!, nilaiPakar: nilai, ); } else { response = await ApiService.updateRuleHama( id: idRule, idGejala: idGejala, idHama: selectedHamaId!, nilaiPakar: nilai, ); } if (response.statusCode != 200 && response.statusCode != 201) { throw Exception("Gagal mengupdate rule"); } } ScaffoldMessenger.of( context, ).showSnackBar(SnackBar(content: Text("Data berhasil diperbarui"))); Navigator.pop(context); } catch (e) { print('Gagal memperbarui data: $e'); ScaffoldMessenger.of( context, ).showSnackBar(SnackBar(content: Text("Gagal memperbarui data"))); } } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: Text("Tambah Rule")), body: Padding( padding: const EdgeInsets.all(16.0), child: isLoading ? Center(child: CircularProgressIndicator()) : Card( elevation: 5, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(8), ), child: Padding( padding: const EdgeInsets.all(16.0), child: ListView( children: [ // Pilih Hama if (!showPenyakitOnly) ...[ Text("Pilih Hama"), DropdownButton( isExpanded: true, value: selectedHamaId, hint: Text('Pilih Hama'), items: hamaList.isNotEmpty ? hamaList.map>(( hama, ) { return DropdownMenuItem( value: hama['id'], child: Text(hama['nama']), ); }).toList() : [ DropdownMenuItem( value: null, child: Text("Data tidak tersedia"), ), ], onChanged: (value) { setState(() { selectedHamaId = value; }); }, ), SizedBox(height: 16), ], // Pilih Penyakit if (!showHamaOnly) ...[ Text("Pilih Penyakit"), DropdownButton( isExpanded: true, value: selectedPenyakitId, hint: Text('Pilih Penyakit'), items: penyakitList.isNotEmpty ? penyakitList.map>(( penyakit, ) { return DropdownMenuItem( value: penyakit['id'], child: Text(penyakit['nama']), ); }).toList() : [ DropdownMenuItem( value: null, child: Text("Data tidak tersedia"), ), ], onChanged: (value) { setState(() { selectedPenyakitId = value; }); }, ), SizedBox(height: 16), ], // Pilih Gejala dan Nilai Pakar Text("Pilih Gejala"), ...List.generate( selectedGejalaIds.length, (index) => Card( elevation: 3, margin: EdgeInsets.only(bottom: 16), child: Padding( padding: const EdgeInsets.all(8.0), child: Row( children: [ // Dropdown untuk gejala Expanded( child: DropdownButton( isExpanded: true, value: selectedGejalaIds[index], hint: Text('Pilih Gejala'), items: gejalaList.isNotEmpty ? gejalaList.map< DropdownMenuItem >((gejala) { return DropdownMenuItem( value: gejala['id'], child: Text(gejala['nama']), ); }).toList() : [ DropdownMenuItem( value: null, child: Text( "Data tidak tersedia", ), ), ], onChanged: (value) { setState(() { selectedGejalaIds[index] = value; }); }, ), ), // Input nilai pakar SizedBox(width: 16), SizedBox( width: 80, child: TextField( keyboardType: TextInputType.number, // Gunakan TextEditingController untuk menampilkan nilai awal controller: TextEditingController( text: nilaiPakarList.length > index ? nilaiPakarList[index] .toString() : "0.5", ), decoration: InputDecoration( labelText: "Nilai Pakar", border: OutlineInputBorder(), ), onChanged: (value) { setState(() { if (value.isNotEmpty) { // Pastikan index ada dalam range if (nilaiPakarList.length <= index) { // Tambahkan nilai baru jika index belum ada nilaiPakarList.add( double.tryParse(value) ?? 0.5, ); } else { // Update nilai jika index sudah ada nilaiPakarList[index] = double.tryParse(value) ?? 0.5; } } }); }, ), ), // Tombol untuk menghapus gejala IconButton( icon: Icon(Icons.remove_circle_outline), onPressed: () { setState(() { selectedGejalaIds.removeAt(index); nilaiPakarList.removeAt(index); }); }, ), ], ), ), ), ), // Tombol untuk menambah gejala ElevatedButton( onPressed: () { setState(() { selectedGejalaIds.add(null); nilaiPakarList.add( 0.5, ); // Menambahkan nilai pakar default }); }, child: Text('Tambah Gejala'), ), SizedBox(height: 20), // Tombol untuk edit rule ElevatedButton( onPressed: () { // Panggil fungsi saveRules untuk menyimpan data updateRules(); }, child: Text('Perbarui Rule'), ), ], ), ), ), ), ); } }