361 lines
15 KiB
Dart
361 lines
15 KiB
Dart
import 'package:flutter/material.dart';
|
|
import 'package:SIBAYAM/admin/edit_rule_page.dart';
|
|
import 'package:http/http.dart' as http;
|
|
import 'package:SIBAYAM/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);
|
|
|
|
@override
|
|
_RulePageState createState() => _RulePageState();
|
|
}
|
|
|
|
class _RulePageState extends State<RulePage> {
|
|
List<Map<String, dynamic>> gejalaList = [];
|
|
List<Map<String, dynamic>> penyakitList = [];
|
|
List<Map<String, dynamic>> hamaList = [];
|
|
|
|
List<dynamic> rules = [];
|
|
bool isLoading = true;
|
|
|
|
// Pagination variables
|
|
int currentPage = 0;
|
|
int rowsPerPage = 10;
|
|
|
|
@override
|
|
void initState() {
|
|
super.initState();
|
|
fetchRules();
|
|
}
|
|
|
|
void fetchRules() async {
|
|
final apiService = ApiService();
|
|
|
|
try {
|
|
// Ambil semua data referensi
|
|
gejalaList = await apiService.getGejala();
|
|
penyakitList = await apiService.getPenyakit();
|
|
hamaList = await apiService.getHama();
|
|
|
|
// Ambil rules penyakit dan hama secara terpisah
|
|
final rulesPenyakit = await apiService.getRulesPenyakit();
|
|
final rulesHama = await apiService.getRulesHama();
|
|
|
|
// Gabungkan dan proses keduanya
|
|
final enrichedRules = [
|
|
// Mengolah rules penyakit
|
|
...rulesPenyakit.map((rule) {
|
|
final gejala = gejalaList.firstWhere(
|
|
(item) => item['id'] == rule['id_gejala'],
|
|
orElse: () => {'nama': '-'},
|
|
);
|
|
|
|
final penyakit = penyakitList.firstWhere(
|
|
(item) => item['id'] == rule['id_penyakit'],
|
|
orElse: () => {'nama': '-'},
|
|
);
|
|
|
|
return {
|
|
'id': rule['id'],
|
|
'id_gejala': rule['id_gejala'],
|
|
'id_penyakit': rule['id_penyakit'],
|
|
'id_hama': null,
|
|
'nama_gejala': gejala['nama'],
|
|
'nama_penyakit': penyakit['nama'],
|
|
'nama_hama': null,
|
|
'nilai_pakar': rule['nilai_pakar'],
|
|
};
|
|
}),
|
|
// Mengolah rules hama
|
|
...rulesHama.map((rule) {
|
|
// Mencari gejala berdasarkan id
|
|
final gejala = gejalaList.firstWhere(
|
|
(item) => item['id'] == rule['id_gejala'],
|
|
orElse: () => {'nama': 'TIDAK DITEMUKAN'},
|
|
);
|
|
|
|
// Mencari hama berdasarkan id
|
|
final hama = hamaList.firstWhere(
|
|
(item) => item['id'] == rule['id_hama'],
|
|
orElse: () => {'nama': 'TIDAK DITEMUKAN'},
|
|
);
|
|
|
|
return {
|
|
'id': rule['id'],
|
|
'id_gejala': rule['id_gejala'],
|
|
'id_penyakit': null,
|
|
'id_hama': rule['id_hama'],
|
|
'nama_gejala': gejala['nama'],
|
|
'nama_penyakit': null,
|
|
'nama_hama': hama['nama'],
|
|
'nilai_pakar': rule['nilai_pakar'],
|
|
};
|
|
}),
|
|
];
|
|
|
|
setState(() {
|
|
rules = enrichedRules;
|
|
});
|
|
} catch (e) {
|
|
print('Terjadi kesalahan saat memuat data: $e');
|
|
} finally {
|
|
setState(() {
|
|
isLoading = false;
|
|
});
|
|
}
|
|
}
|
|
|
|
Future<void> deleteRule(Map<String, dynamic> rule) async {
|
|
try {
|
|
http.Response res;
|
|
|
|
// Tentukan fungsi delete berdasarkan isi rule
|
|
if (rule['id_hama'] != null) {
|
|
res = await ApiService.deleteRuleHama(rule['id']); // Fungsi API untuk delete hama
|
|
} else if (rule['id_penyakit'] != null) {
|
|
res = await ApiService.deleteRulePenyakit(rule['id']); // Fungsi API untuk delete penyakit
|
|
} else {
|
|
throw Exception("Data rule tidak valid (tidak ada id_hama atau id_penyakit)");
|
|
}
|
|
|
|
if (res.statusCode == 200) {
|
|
ScaffoldMessenger.of(context).showSnackBar(
|
|
SnackBar(content: Text("Rule berhasil dihapus"))
|
|
);
|
|
fetchRules(); // Refresh data setelah delete
|
|
} else {
|
|
throw Exception("Gagal menghapus rule");
|
|
}
|
|
} catch (e) {
|
|
ScaffoldMessenger.of(context).showSnackBar(
|
|
SnackBar(content: Text("Terjadi kesalahan saat menghapus: $e")),
|
|
);
|
|
}
|
|
}
|
|
|
|
// Get paginated data
|
|
List<dynamic> get paginatedRules {
|
|
final startIndex = currentPage * rowsPerPage;
|
|
final endIndex = startIndex + rowsPerPage > rules.length ? rules.length : startIndex + rowsPerPage;
|
|
|
|
if (startIndex >= rules.length) {
|
|
return [];
|
|
}
|
|
|
|
return rules.sublist(startIndex, endIndex);
|
|
}
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return Scaffold(
|
|
appBar: AppBar(title: const Text('Data Rules')),
|
|
body: Padding(
|
|
padding: const EdgeInsets.all(16.0),
|
|
child: Column(
|
|
children: [
|
|
Row(
|
|
mainAxisAlignment: MainAxisAlignment.end,
|
|
children: [
|
|
// Button untuk tambah rule hama
|
|
ElevatedButton.icon(
|
|
onPressed: () {
|
|
Navigator.push(
|
|
context,
|
|
MaterialPageRoute(
|
|
builder: (context) => TambahRulePage(
|
|
isEditing: false,
|
|
isEditingHama: true, // Menandakan ini adalah rule hama
|
|
selectedRuleIds: [],
|
|
selectedGejalaIds: [],
|
|
nilaiPakarList: [],
|
|
selectedHamaId: null,
|
|
selectedPenyakitId: null,
|
|
showHamaOnly: true, // Parameter baru untuk menampilkan hanya dropdown hama
|
|
),
|
|
),
|
|
).then((_) => fetchRules());
|
|
},
|
|
icon: Icon(Icons.bug_report, size: 16,),
|
|
label: Text(
|
|
"Tambah Rule Hama",
|
|
style: TextStyle(fontSize: 12)),
|
|
style: ElevatedButton.styleFrom(
|
|
backgroundColor: Colors.green,
|
|
foregroundColor: Colors.white,
|
|
padding: EdgeInsets.symmetric(horizontal: 8, vertical: 6), // Padding lebih kecil
|
|
minimumSize: Size(0, 32), // Tinggi minimum lebih kecil
|
|
tapTargetSize: MaterialTapTargetSize.shrinkWrap, // Mengurangi area tap
|
|
),
|
|
),
|
|
SizedBox(width: 10),
|
|
// Button untuk tambah rule penyakit
|
|
ElevatedButton.icon(
|
|
onPressed: () {
|
|
Navigator.push(
|
|
context,
|
|
MaterialPageRoute(
|
|
builder: (context) => TambahRulePage(
|
|
isEditing: false,
|
|
isEditingHama: false, // Menandakan ini adalah rule penyakit
|
|
selectedRuleIds: [],
|
|
selectedGejalaIds: [],
|
|
nilaiPakarList: [],
|
|
selectedHamaId: null,
|
|
selectedPenyakitId: null,
|
|
showPenyakitOnly: true, // Parameter baru untuk menampilkan hanya dropdown penyakit
|
|
),
|
|
),
|
|
).then((_) => fetchRules());
|
|
},
|
|
icon: Icon(Icons.healing, size: 16,),
|
|
label: Text(
|
|
"Tambah Rule Penyakit",
|
|
style: TextStyle(fontSize: 12),),
|
|
style: ElevatedButton.styleFrom(
|
|
backgroundColor: Colors.blue,
|
|
foregroundColor: Colors.white,
|
|
padding: EdgeInsets.symmetric(horizontal: 8, vertical: 6), // Padding lebih kecil
|
|
minimumSize: Size(0, 32), // Tinggi minimum lebih kecil
|
|
tapTargetSize: MaterialTapTargetSize.shrinkWrap, // Mengurangi area tap
|
|
),
|
|
),
|
|
],
|
|
),
|
|
const SizedBox(height: 16),
|
|
isLoading
|
|
? const Center(child: CircularProgressIndicator())
|
|
: Expanded(
|
|
child: Column(
|
|
children: [
|
|
Expanded(
|
|
child: SingleChildScrollView(
|
|
scrollDirection: Axis.horizontal,
|
|
child: SingleChildScrollView(
|
|
scrollDirection: Axis.vertical,
|
|
child: DataTable(
|
|
headingRowColor: MaterialStateProperty.resolveWith<Color>(
|
|
(Set<MaterialState> states) {
|
|
return Color(0xFF9DC08D); // Apply color to all header rows
|
|
},
|
|
),
|
|
columns: const [
|
|
DataColumn(label: Text('No')),
|
|
DataColumn(label: Text('Hama & Penyakit')),
|
|
DataColumn(label: Text('Gejala')),
|
|
DataColumn(label: Text('Nilai Pakar')),
|
|
DataColumn(label: Text('Aksi')),
|
|
],
|
|
rows: List.generate(paginatedRules.length, (index) {
|
|
final rule = paginatedRules[index];
|
|
final displayIndex = currentPage * rowsPerPage + index + 1;
|
|
|
|
final namaKategori = rule['id_penyakit'] != null
|
|
? rule['nama_penyakit'] ?? '-'
|
|
: rule['nama_hama'] ?? '-';
|
|
|
|
final isPenyakit = rule['id_penyakit'] != null;
|
|
|
|
return DataRow(
|
|
cells: [
|
|
DataCell(Text(displayIndex.toString())),
|
|
DataCell(Text(namaKategori)),
|
|
DataCell(Text(rule['nama_gejala'] ?? '-')),
|
|
DataCell(Text(rule['nilai_pakar']?.toString() ?? '-')),
|
|
DataCell(
|
|
Row(
|
|
children: [
|
|
IconButton(
|
|
icon: const Icon(
|
|
Icons.edit,
|
|
color: Colors.orange,
|
|
),
|
|
onPressed: () {
|
|
if (rule != null &&
|
|
rule['id'] != null &&
|
|
rule['id_gejala'] != null &&
|
|
rule['nilai_pakar'] != null) {
|
|
// Tentukan jenis rule untuk editing
|
|
final bool editingHama = rule['id_hama'] != null;
|
|
|
|
Navigator.push(
|
|
context,
|
|
MaterialPageRoute(
|
|
builder: (context) => EditRulePage(
|
|
isEditing: true,
|
|
isEditingHama: editingHama,
|
|
selectedRuleIds: [rule['id'] as int],
|
|
selectedGejalaIds: [rule['id_gejala'] as int],
|
|
nilaiPakarList: [(rule['nilai_pakar'] as num).toDouble()],
|
|
selectedHamaId: rule['id_hama'] as int?,
|
|
selectedPenyakitId: rule['id_penyakit'] as int?,
|
|
// Tambahkan parameter untuk menentukan dropdown yang ditampilkan
|
|
showHamaOnly: editingHama,
|
|
showPenyakitOnly: !editingHama,
|
|
),
|
|
),
|
|
).then((_) => fetchRules());
|
|
} else {
|
|
// 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");
|
|
}
|
|
},
|
|
),
|
|
IconButton(
|
|
icon: const Icon(
|
|
Icons.delete,
|
|
color: Colors.red,
|
|
),
|
|
onPressed: () {
|
|
deleteRule(rule);
|
|
},
|
|
),
|
|
],
|
|
),
|
|
),
|
|
],
|
|
);
|
|
}),
|
|
),
|
|
),
|
|
),
|
|
),
|
|
// Pagination controls
|
|
Container(
|
|
padding: EdgeInsets.symmetric(vertical: 8.0),
|
|
child: Row(
|
|
mainAxisAlignment: MainAxisAlignment.center,
|
|
children: [
|
|
IconButton(
|
|
icon: Icon(Icons.chevron_left),
|
|
onPressed: currentPage > 0
|
|
? () => setState(() => currentPage--)
|
|
: null,
|
|
),
|
|
Text('Halaman ${currentPage + 1} dari ${(rules.length / rowsPerPage).ceil()}'),
|
|
IconButton(
|
|
icon: Icon(Icons.chevron_right),
|
|
onPressed: (currentPage + 1) * rowsPerPage < rules.length
|
|
? () => setState(() => currentPage++)
|
|
: null,
|
|
),
|
|
],
|
|
),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
);
|
|
}
|
|
} |