454 lines
18 KiB
Dart
454 lines
18 KiB
Dart
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<int> selectedRuleIds;
|
|
final List<int> selectedGejalaIds;
|
|
final List<double> 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<EditRulePage> {
|
|
int? selectedHamaId;
|
|
int? selectedPenyakitId;
|
|
List<int?> selectedGejalaIds = [null];
|
|
List<double> nilaiPakarList = [0.5];
|
|
List<int?> 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<Map<String, dynamic>> hamaList = [];
|
|
List<Map<String, dynamic>> penyakitList = [];
|
|
List<Map<String, dynamic>> 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<String, dynamic>) {
|
|
// 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<int?>((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<int?>((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<double>((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<void> 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<int?>.from(widget.selectedRuleIds);
|
|
}
|
|
if (widget.selectedGejalaIds.isNotEmpty) {
|
|
selectedGejalaIds = List<int?>.from(widget.selectedGejalaIds);
|
|
}
|
|
if (widget.nilaiPakarList.isNotEmpty) {
|
|
nilaiPakarList = List<double>.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<int>(
|
|
isExpanded: true,
|
|
value: selectedHamaId,
|
|
hint: Text('Pilih Hama'),
|
|
items:
|
|
hamaList.isNotEmpty
|
|
? hamaList.map<DropdownMenuItem<int>>((
|
|
hama,
|
|
) {
|
|
return DropdownMenuItem<int>(
|
|
value: hama['id'],
|
|
child: Text(hama['nama']),
|
|
);
|
|
}).toList()
|
|
: [
|
|
DropdownMenuItem<int>(
|
|
value: null,
|
|
child: Text("Data tidak tersedia"),
|
|
),
|
|
],
|
|
onChanged: (value) {
|
|
setState(() {
|
|
selectedHamaId = value;
|
|
});
|
|
},
|
|
),
|
|
SizedBox(height: 16),
|
|
],
|
|
|
|
// Pilih Penyakit
|
|
if (!showHamaOnly) ...[
|
|
Text("Pilih Penyakit"),
|
|
DropdownButton<int>(
|
|
isExpanded: true,
|
|
value: selectedPenyakitId,
|
|
hint: Text('Pilih Penyakit'),
|
|
items:
|
|
penyakitList.isNotEmpty
|
|
? penyakitList.map<DropdownMenuItem<int>>((
|
|
penyakit,
|
|
) {
|
|
return DropdownMenuItem<int>(
|
|
value: penyakit['id'],
|
|
child: Text(penyakit['nama']),
|
|
);
|
|
}).toList()
|
|
: [
|
|
DropdownMenuItem<int>(
|
|
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<int>(
|
|
isExpanded: true,
|
|
value: selectedGejalaIds[index],
|
|
hint: Text('Pilih Gejala'),
|
|
items:
|
|
gejalaList.isNotEmpty
|
|
? gejalaList.map<
|
|
DropdownMenuItem<int>
|
|
>((gejala) {
|
|
return DropdownMenuItem<int>(
|
|
value: gejala['id'],
|
|
child: Text(gejala['nama']),
|
|
);
|
|
}).toList()
|
|
: [
|
|
DropdownMenuItem<int>(
|
|
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'),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
),
|
|
),
|
|
);
|
|
}
|
|
}
|