edit rule and delete fungction integrasi

This commit is contained in:
unknown 2025-05-03 03:02:03 +07:00
parent 692bfeeb50
commit d22720c399
4 changed files with 545 additions and 76 deletions

View File

@ -0,0 +1,438 @@
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;
const EditRulePage({
Key? key,
required this.isEditing,
required this.isEditingHama,
required this.selectedRuleIds,
required this.selectedGejalaIds,
required this.nilaiPakarList,
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;
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();
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
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
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'),
),
],
),
),
),
),
);
}
}

View File

@ -1,7 +1,9 @@
import 'package:flutter/material.dart';
import 'package:frontend/admin/edit_rule_page.dart';
import 'package:http/http.dart' as http;
import 'package:frontend/api_services/api_services.dart';
import 'tambah_rule_page.dart';
import 'edit_hama_page.dart';
class RulePage extends StatefulWidget {
const RulePage({Key? key}) : super(key: key);
@ -241,29 +243,49 @@ class _RulePageState extends State<RulePage> {
color: Colors.orange,
),
onPressed: () {
if (rule != null && rule.id != null) {
if (rule != null &&
rule['id'] != null &&
rule['id_gejala'] != null &&
rule['nilai_pakar'] != null) {
Navigator.push(
context,
MaterialPageRoute(
builder:
(context) => TambahRulePage(
(context) => EditRulePage(
isEditing: true,
isEditingHama: true,
selectedRuleIds: [rule.id],
selectedRuleIds: [
rule['id'] as int,
],
selectedGejalaIds: [
rule.idGejala,
rule['id_gejala'] as int,
],
nilaiPakarList: [
rule.nilaiPakar,
(rule['nilai_pakar'] as num)
.toDouble(),
],
selectedHamaId: rule.idHama,
selectedHamaId:
rule['id_hama']
as int?,
selectedPenyakitId: rule['id_penyakit'] as int?, // Tambahkan type cast ke int?
),
),
);
} else {
print(
'Data rule tidak lengkap atau null',
// Tampilkan pesan error jika data rule tidak lengkap
ScaffoldMessenger.of(
context,
).showSnackBar(
SnackBar(
content: Text(
"Data rule tidak lengkap atau tidak valid",
),
backgroundColor: Colors.red,
),
);
// Debug info
print("Rule data: $rule");
}
},
),

View File

@ -27,7 +27,6 @@ class TambahRulePage extends StatefulWidget {
}
class _TambahRulePageState extends State<TambahRulePage> {
int? selectedHamaId;
int? selectedPenyakitId;
List<int?> selectedGejalaIds = [null];
@ -45,25 +44,37 @@ class _TambahRulePageState extends State<TambahRulePage> {
List<Map<String, dynamic>> penyakitList = [];
List<Map<String, dynamic>> gejalaList = [];
void loadRulesForEditing() async {
try {
final fetchedRules = isEditing
? await api.getRulesHama()
: await api.getRulesPenyakit();
setState(() {
selectedRuleIds = fetchedRules.map<int>((rule) => rule['id']).toList();
selectedGejalaIds = fetchedRules.map<int>((rule) => rule['id_gejala']).toList();
nilaiPakarList = fetchedRules.map<double>((rule) => (rule['nilai_pakar'] as num).toDouble()).toList();
});
} catch (e) {
print("Gagal memuat data rule: $e");
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text("Gagal memuat data rule")),
);
}
}
// void loadRulesForEditing() async {
// try {
// final fetchedRules =
// isEditing ? await api.getRulesHama() : await api.getRulesPenyakit();
// setState(() {
// final validRules =
// fetchedRules
// .where(
// (rule) =>
// rule != null &&
// rule.containsKey('id') &&
// rule.containsKey('id_gejala') &&
// rule.containsKey('nilai_pakar') &&
// rule['id'] != null &&
// rule['id_gejala'] != null &&
// rule['nilai_pakar'] != null,
// )
// .toList();
// selectedRuleIds = fetchedRules.map<int>((rule) => rule['id'] ?? 0).toList();
// selectedGejalaIds = validRules.map<int>((rule) => rule['id_gejala']).toList();
// nilaiPakarList = validRules.map<double>((rule) => (rule['nilai_pakar'] as num).toDouble()).toList();
// });
// print('Fetched Rules: $fetchedRules');
// print('First Rule: ${fetchedRules.first}');
// } catch (e) {
// print("Gagal memuat data rule: $e");
// ScaffoldMessenger.of(
// context,
// ).showSnackBar(SnackBar(content: Text("Gagal memuat data rule")));
// }
// }
// Fungsi untuk fetch data dari API
Future<void> fetchData() async {
@ -162,57 +173,56 @@ class _TambahRulePageState extends State<TambahRulePage> {
}
}
void updateRules() async {
if (selectedPenyakitId == null && selectedHamaId == null) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text("Pilih minimal satu: Penyakit atau Hama")),
);
return;
}
// void updateRules() async {
// if (selectedPenyakitId == null && selectedHamaId == null) {
// ScaffoldMessenger.of(context).showSnackBar(
// SnackBar(content: Text("Pilih minimal satu: Penyakit atau Hama")),
// );
// return;
// }
try {
for (int i = 0; i < selectedGejalaIds.length; i++) {
final idRule = selectedRuleIds[i];
final idGejala = selectedGejalaIds[i];
final nilai = nilaiPakarList[i];
// 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) {
http.Response response;
// if (idRule != null && idGejala != null) {
// 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 (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")),
);
}
}
// 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) {

View File

@ -7,8 +7,7 @@ class ApiService {
static const String gejalaUrl = 'http://localhost:5000/api/gejala';
static const String hamaUrl = 'http://localhost:5000/api/hama';
static const String penyakitUrl = 'http://localhost:5000/api/penyakit';
static const String rulesPenyakitUrl =
'http://localhost:5000/api/rules_penyakit';
static const String rulesPenyakitUrl ='http://localhost:5000/api/rules_penyakit';
static const String rulesHamaUrl = 'http://localhost:5000/api/rules_hama';
// Fungsi Login (dengan perbaikan)