integrasi add rules
This commit is contained in:
parent
4271210c03
commit
692bfeeb50
|
@ -9,6 +9,7 @@ const gejalaRoutes = require('./routes/gejalaRoute');
|
||||||
const hamaRoutes = require('./routes/hamaRoutes');
|
const hamaRoutes = require('./routes/hamaRoutes');
|
||||||
const penyakitRoutes = require('./routes/penyakitRoutes');
|
const penyakitRoutes = require('./routes/penyakitRoutes');
|
||||||
const ruleRoutes = require('./routes/ruleRoutes');
|
const ruleRoutes = require('./routes/ruleRoutes');
|
||||||
|
const ruleHamaRoutes = require('./routes/ruleHamaRoutes');
|
||||||
const swaggerDocs = require('./swagger');
|
const swaggerDocs = require('./swagger');
|
||||||
|
|
||||||
dotenv.config();
|
dotenv.config();
|
||||||
|
@ -25,7 +26,8 @@ app.use("/api/auth", authRoutes);
|
||||||
app.use("/api/gejala", gejalaRoutes);
|
app.use("/api/gejala", gejalaRoutes);
|
||||||
app.use("/api/hama", hamaRoutes);
|
app.use("/api/hama", hamaRoutes);
|
||||||
app.use("/api/penyakit", penyakitRoutes);
|
app.use("/api/penyakit", penyakitRoutes);
|
||||||
app.use("/api/rules", ruleRoutes);
|
app.use("/api/rules_penyakit", ruleRoutes);
|
||||||
|
app.use("/api/rules_hama", ruleHamaRoutes);
|
||||||
|
|
||||||
|
|
||||||
// Swagger Documentation
|
// Swagger Documentation
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
const jwt = require('jsonwebtoken');
|
const jwt = require('jsonwebtoken');
|
||||||
const argon2 = require('argon2');
|
const argon2 = require('argon2');
|
||||||
const randomstring = require('randomstring');
|
const randomstring = require('randomstring');
|
||||||
const User = require('../models/user'); // Pastikan sesuai dengan struktur project
|
const {User} = require('../models'); // Pastikan sesuai dengan struktur project
|
||||||
require('dotenv').config();
|
require('dotenv').config();
|
||||||
|
|
||||||
// Fungsi untuk membuat token JWT
|
// Fungsi untuk membuat token JWT
|
||||||
|
@ -13,7 +13,6 @@ const generateToken = (user) => {
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
// Menambahkan user baru dengan hashing Argon2
|
// Menambahkan user baru dengan hashing Argon2
|
||||||
exports.register = async (req, res) => {
|
exports.register = async (req, res) => {
|
||||||
try {
|
try {
|
||||||
|
|
|
@ -1,9 +1,11 @@
|
||||||
const Gejala = require('../models/gejala');
|
const {Gejala} = require('../models');
|
||||||
|
|
||||||
// 🔹 Menampilkan semua data gejala
|
// 🔹 Menampilkan semua data gejala
|
||||||
exports.getAllGejala = async (req, res) => {
|
exports.getAllGejala = async (req, res) => {
|
||||||
try {
|
try {
|
||||||
const gejala = await Gejala.findAll();
|
const gejala = await Gejala.findAll({
|
||||||
|
attributes: ['id', 'nama']
|
||||||
|
});
|
||||||
res.status(200).json(gejala);
|
res.status(200).json(gejala);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
res.status(500).json({ message: 'Terjadi kesalahan', error });
|
res.status(500).json({ message: 'Terjadi kesalahan', error });
|
||||||
|
|
|
@ -1,9 +1,11 @@
|
||||||
const Hama = require('../models/hama');
|
const {Hama} = require('../models');
|
||||||
|
|
||||||
// 🔹 Fungsi untuk mendapatkan semua data hama
|
// 🔹 Fungsi untuk mendapatkan semua data hama
|
||||||
exports.getAllHama = async (req, res) => {
|
exports.getAllHama = async (req, res) => {
|
||||||
try {
|
try {
|
||||||
const dataHama = await Hama.findAll();
|
const dataHama = await Hama.findAll({
|
||||||
|
attributes: ['id', 'nama' , 'deskripsi' , 'penanganan']
|
||||||
|
});
|
||||||
res.status(200).json({ message: 'Data hama berhasil diambil', data: dataHama });
|
res.status(200).json({ message: 'Data hama berhasil diambil', data: dataHama });
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
res.status(500).json({ message: 'Gagal mengambil data hama', error });
|
res.status(500).json({ message: 'Gagal mengambil data hama', error });
|
||||||
|
|
|
@ -1,9 +1,11 @@
|
||||||
const Penyakit = require('../models/penyakit');
|
const {Penyakit} = require('../models');
|
||||||
|
|
||||||
// 🔹 Fungsi untuk mendapatkan semua data penyakit
|
// 🔹 Fungsi untuk mendapatkan semua data penyakit
|
||||||
exports.getAllPenyakit = async (req, res) => {
|
exports.getAllPenyakit = async (req, res) => {
|
||||||
try {
|
try {
|
||||||
const dataPenyakit = await Penyakit.findAll();
|
const dataPenyakit = await Penyakit.findAll({
|
||||||
|
attributes: ['id', 'nama' , 'deskripsi' , 'penanganan']
|
||||||
|
});
|
||||||
res.status(200).json({ message: 'Data penyakit berhasil diambil', data: dataPenyakit });
|
res.status(200).json({ message: 'Data penyakit berhasil diambil', data: dataPenyakit });
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
res.status(500).json({ message: 'Gagal mengambil data penyakit', error });
|
res.status(500).json({ message: 'Gagal mengambil data penyakit', error });
|
||||||
|
|
|
@ -1,19 +1,18 @@
|
||||||
const { Rule, gejala, penyakit, hama } = require('../models');
|
const { Rule_penyakit } = require('../models');
|
||||||
|
|
||||||
// 🔥 Buat aturan baru
|
// 🔥 Buat aturan baru
|
||||||
exports.createRule = async (req, res) => {
|
exports.createRulePenyakit = async (req, res) => {
|
||||||
try {
|
try {
|
||||||
const { id_gejala, id_penyakit, id_hama, nilai_pakar } = req.body;
|
const { id_gejala, id_penyakit, nilai_pakar } = req.body;
|
||||||
|
|
||||||
// Validasi minimal
|
// Validasi minimal
|
||||||
if (!id_gejala || (!id_penyakit && !id_hama) || !nilai_pakar) {
|
if (!id_gejala || (!id_penyakit) || !nilai_pakar) {
|
||||||
return res.status(400).json({ message: 'Data tidak lengkap' });
|
return res.status(400).json({ message: 'Data tidak lengkap' });
|
||||||
}
|
}
|
||||||
|
|
||||||
const newRule = await Rule.create({
|
const newRule = await Rule_penyakit.create({
|
||||||
id_gejala,
|
id_gejala,
|
||||||
id_penyakit,
|
id_penyakit,
|
||||||
id_hama,
|
|
||||||
nilai_pakar
|
nilai_pakar
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -25,9 +24,9 @@ exports.createRule = async (req, res) => {
|
||||||
};
|
};
|
||||||
|
|
||||||
// 🔥 Ambil semua aturan
|
// 🔥 Ambil semua aturan
|
||||||
exports.getRules = async (req, res) => {
|
exports.getRulesPenyakit = async (req, res) => {
|
||||||
try {
|
try {
|
||||||
const rules = await Rule.findAll();
|
const rules = await Rule_penyakit.findAll();
|
||||||
|
|
||||||
res.status(200).json({ message: 'Daftar Rules', data: rules });
|
res.status(200).json({ message: 'Daftar Rules', data: rules });
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
@ -37,12 +36,12 @@ exports.getRules = async (req, res) => {
|
||||||
};
|
};
|
||||||
|
|
||||||
// 🔥 Update aturan
|
// 🔥 Update aturan
|
||||||
exports.updateRule = async (req, res) => {
|
exports.updateRulePenyakit = async (req, res) => {
|
||||||
try {
|
try {
|
||||||
const { id } = req.params;
|
const { id } = req.params;
|
||||||
const { id_gejala, id_penyakit, id_hama, nilai_pakar } = req.body;
|
const { id_gejala, id_penyakit, nilai_pakar } = req.body;
|
||||||
|
|
||||||
const rule = await Rule.findByPk(id);
|
const rule = await Rule_penyakit.findByPk(id);
|
||||||
if (!rule) {
|
if (!rule) {
|
||||||
return res.status(404).json({ message: 'Rule tidak ditemukan' });
|
return res.status(404).json({ message: 'Rule tidak ditemukan' });
|
||||||
}
|
}
|
||||||
|
@ -50,7 +49,6 @@ exports.updateRule = async (req, res) => {
|
||||||
await rule.update({
|
await rule.update({
|
||||||
id_gejala,
|
id_gejala,
|
||||||
id_penyakit,
|
id_penyakit,
|
||||||
id_hama,
|
|
||||||
nilai_pakar
|
nilai_pakar
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -62,11 +60,11 @@ exports.updateRule = async (req, res) => {
|
||||||
};
|
};
|
||||||
|
|
||||||
// 🔥 Hapus aturan
|
// 🔥 Hapus aturan
|
||||||
exports.deleteRule = async (req, res) => {
|
exports.deleteRulePenyakit = async (req, res) => {
|
||||||
try {
|
try {
|
||||||
const { id } = req.params;
|
const { id } = req.params;
|
||||||
|
|
||||||
const rule = await Rule.findByPk(id);
|
const rule = await Rule_penyakit.findByPk(id);
|
||||||
if (!rule) {
|
if (!rule) {
|
||||||
return res.status(404).json({ message: 'Rule tidak ditemukan' });
|
return res.status(404).json({ message: 'Rule tidak ditemukan' });
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,79 @@
|
||||||
|
const { Rule_hama } = require('../models');
|
||||||
|
|
||||||
|
// 🔥 Buat aturan baru
|
||||||
|
exports.createRuleHama = async (req, res) => {
|
||||||
|
try {
|
||||||
|
const { id_gejala, id_hama, nilai_pakar } = req.body;
|
||||||
|
|
||||||
|
// Validasi minimal
|
||||||
|
if (!id_gejala || (!id_hama) || !nilai_pakar) {
|
||||||
|
return res.status(400).json({ message: 'Data tidak lengkap' });
|
||||||
|
}
|
||||||
|
|
||||||
|
const newRule = await Rule_hama.create({
|
||||||
|
id_gejala,
|
||||||
|
id_hama,
|
||||||
|
nilai_pakar
|
||||||
|
});
|
||||||
|
|
||||||
|
res.status(201).json({ message: 'Rule berhasil dibuat', data: newRule });
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error createRule:', error);
|
||||||
|
res.status(500).json({ message: 'Terjadi kesalahan server', error: error.message });
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// 🔥 Ambil semua aturan
|
||||||
|
exports.getRulesHama = async (req, res) => {
|
||||||
|
try {
|
||||||
|
const rules = await Rule_hama.findAll();
|
||||||
|
|
||||||
|
res.status(200).json({ message: 'Daftar Rules', data: rules });
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error getRules:', error);
|
||||||
|
res.status(500).json({ message: 'Terjadi kesalahan server', error: error.message });
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// 🔥 Update aturan
|
||||||
|
exports.updateRuleHama = async (req, res) => {
|
||||||
|
try {
|
||||||
|
const { id } = req.params;
|
||||||
|
const { id_gejala, id_hama, nilai_pakar } = req.body;
|
||||||
|
|
||||||
|
const rule = await Rule_hama.findByPk(id);
|
||||||
|
if (!rule) {
|
||||||
|
return res.status(404).json({ message: 'Rule tidak ditemukan' });
|
||||||
|
}
|
||||||
|
|
||||||
|
await rule.update({
|
||||||
|
id_gejala,
|
||||||
|
id_hama,
|
||||||
|
nilai_pakar
|
||||||
|
});
|
||||||
|
|
||||||
|
res.status(200).json({ message: 'Rule berhasil diperbarui', data: rule });
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error updateRule:', error);
|
||||||
|
res.status(500).json({ message: 'Terjadi kesalahan server', error: error.message });
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// 🔥 Hapus aturan
|
||||||
|
exports.deleteRuleHama = async (req, res) => {
|
||||||
|
try {
|
||||||
|
const { id } = req.params;
|
||||||
|
|
||||||
|
const rule = await Rule_hama.findByPk(id);
|
||||||
|
if (!rule) {
|
||||||
|
return res.status(404).json({ message: 'Rule tidak ditemukan' });
|
||||||
|
}
|
||||||
|
|
||||||
|
await rule.destroy();
|
||||||
|
|
||||||
|
res.status(200).json({ message: 'Rule berhasil dihapus' });
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error deleteRule:', error);
|
||||||
|
res.status(500).json({ message: 'Terjadi kesalahan server', error: error.message });
|
||||||
|
}
|
||||||
|
};
|
|
@ -1,4 +1,4 @@
|
||||||
const User = require('../models/user');
|
const {User} = require('../models');
|
||||||
const argon2 = require('argon2');
|
const argon2 = require('argon2');
|
||||||
const { Op } = require('sequelize');
|
const { Op } = require('sequelize');
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
/** @type {import('sequelize-cli').Migration} */
|
/** @type {import('sequelize-cli').Migration} */
|
||||||
module.exports = {
|
module.exports = {
|
||||||
async up(queryInterface, Sequelize) {
|
async up(queryInterface, Sequelize) {
|
||||||
await queryInterface.createTable('Rules', {
|
await queryInterface.createTable('Rules_penyakit', {
|
||||||
id: {
|
id: {
|
||||||
allowNull: false,
|
allowNull: false,
|
||||||
autoIncrement: true,
|
autoIncrement: true,
|
||||||
|
@ -27,16 +27,9 @@ module.exports = {
|
||||||
key:'id'
|
key:'id'
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
id_hama: {
|
|
||||||
type: Sequelize.INTEGER,
|
|
||||||
references:{
|
|
||||||
model: 'hama',
|
|
||||||
key: 'id'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
async down(queryInterface, Sequelize) {
|
async down(queryInterface, Sequelize) {
|
||||||
await queryInterface.dropTable('Rules');
|
await queryInterface.dropTable('Rules_penyakit');
|
||||||
}
|
}
|
||||||
};
|
};
|
|
@ -0,0 +1,34 @@
|
||||||
|
'use strict';
|
||||||
|
/** @type {import('sequelize-cli').Migration} */
|
||||||
|
module.exports = {
|
||||||
|
async up(queryInterface, Sequelize) {
|
||||||
|
await queryInterface.createTable('Rules_hama', {
|
||||||
|
id: {
|
||||||
|
allowNull: false,
|
||||||
|
autoIncrement: true,
|
||||||
|
primaryKey: true,
|
||||||
|
type: Sequelize.INTEGER
|
||||||
|
},
|
||||||
|
id_gejala: {
|
||||||
|
type: Sequelize.INTEGER,
|
||||||
|
references: {
|
||||||
|
model: 'gejala',
|
||||||
|
key: 'id'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
nilai_pakar: {
|
||||||
|
type: Sequelize.FLOAT
|
||||||
|
},
|
||||||
|
id_hama: {
|
||||||
|
type: Sequelize.INTEGER,
|
||||||
|
references: {
|
||||||
|
model: 'hama',
|
||||||
|
key: 'id'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
});
|
||||||
|
},
|
||||||
|
async down(queryInterface, Sequelize) {
|
||||||
|
await queryInterface.dropTable('Rules_hama');
|
||||||
|
}
|
||||||
|
};
|
|
@ -1,4 +1,5 @@
|
||||||
const { Model, DataTypes } = require('sequelize');
|
const { Model, DataTypes } = require('sequelize');
|
||||||
|
const sequelize = require('../config/database');
|
||||||
|
|
||||||
module.exports = (sequelize) => {
|
module.exports = (sequelize) => {
|
||||||
class Gejala extends Model {}
|
class Gejala extends Model {}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
const { Model, DataTypes } = require('sequelize');
|
const { Model, DataTypes } = require('sequelize');
|
||||||
|
const sequelize = require('../config/database');
|
||||||
|
|
||||||
module.exports = (sequelize) => {
|
module.exports = (sequelize) => {
|
||||||
class Hama extends Model {}
|
class Hama extends Model {}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
const { Model, DataTypes } = require('sequelize');
|
const { Model, DataTypes } = require('sequelize');
|
||||||
|
const sequelize = require('../config/database');
|
||||||
|
|
||||||
module.exports =(sequelize) => {
|
module.exports =(sequelize) => {
|
||||||
class Penyakit extends Model {}
|
class Penyakit extends Model {}
|
||||||
|
|
|
@ -0,0 +1,57 @@
|
||||||
|
const { Model, DataTypes } = require('sequelize');
|
||||||
|
const sequelize = require('../config/database');
|
||||||
|
|
||||||
|
module.exports = (sequelize) => {
|
||||||
|
|
||||||
|
class Rule_hama extends Model {
|
||||||
|
static associate(models) {
|
||||||
|
// Asosiasi dengan model Gejala
|
||||||
|
Rule_hama.belongsTo(models.Gejala, {
|
||||||
|
foreignKey: 'id_gejala',
|
||||||
|
as: 'gejala', // Nama asosiasi yang bisa digunakan saat melakukan query
|
||||||
|
});
|
||||||
|
|
||||||
|
// Asosiasi dengan model hama
|
||||||
|
Rule_hama.belongsTo(models.Hama, {
|
||||||
|
foreignKey: 'id_hama',
|
||||||
|
as: 'hama',
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Rule_hama.init(
|
||||||
|
{
|
||||||
|
id_gejala: {
|
||||||
|
type: DataTypes.INTEGER,
|
||||||
|
allowNull: true,
|
||||||
|
references: {
|
||||||
|
model: 'gejala', // Mengacu ke tabel 'gejala'
|
||||||
|
key: 'id', // Mengacu ke kolom 'id' pada tabel 'gejala'
|
||||||
|
},
|
||||||
|
},
|
||||||
|
nilai_pakar: {
|
||||||
|
type: DataTypes.FLOAT,
|
||||||
|
allowNull: false,
|
||||||
|
},
|
||||||
|
id_hama: {
|
||||||
|
type: DataTypes.INTEGER,
|
||||||
|
allowNull: true,
|
||||||
|
references: {
|
||||||
|
model: 'hama',
|
||||||
|
key: 'id',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
sequelize,
|
||||||
|
modelName: 'Rule_hama',
|
||||||
|
tableName: 'rules_hama',
|
||||||
|
timestamps: false,
|
||||||
|
paranoid: false,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
return Rule_hama;
|
||||||
|
|
||||||
|
}
|
|
@ -1,31 +1,26 @@
|
||||||
const { Model, DataTypes } = require('sequelize');
|
const { Model, DataTypes } = require('sequelize');
|
||||||
|
const sequelize = require('../config/database');
|
||||||
|
|
||||||
module.exports = (sequelize) => {
|
module.exports = (sequelize) => {
|
||||||
|
|
||||||
class Rule extends Model {
|
class Rule_penyakit extends Model {
|
||||||
static associate(models) {
|
static associate(models) {
|
||||||
// Asosiasi dengan model Gejala
|
// Asosiasi dengan model Gejala
|
||||||
Rule.belongsTo(models.Gejala, {
|
Rule_penyakit.belongsTo(models.Gejala, {
|
||||||
foreignKey: 'id_gejala',
|
foreignKey: 'id_gejala',
|
||||||
as: 'gejala', // Nama asosiasi yang bisa digunakan saat melakukan query
|
as: 'gejala', // Nama asosiasi yang bisa digunakan saat melakukan query
|
||||||
});
|
});
|
||||||
|
|
||||||
// Asosiasi dengan model Penyakit
|
// Asosiasi dengan model Penyakit
|
||||||
Rule.belongsTo(models.Penyakit, {
|
Rule_penyakit.belongsTo(models.Penyakit, {
|
||||||
foreignKey: 'id_penyakit',
|
foreignKey: 'id_penyakit',
|
||||||
as: 'penyakit',
|
as: 'penyakit',
|
||||||
});
|
});
|
||||||
|
|
||||||
// Asosiasi dengan model Hama
|
|
||||||
Rule.belongsTo(models.Hama, {
|
|
||||||
foreignKey: 'id_hama',
|
|
||||||
as: 'hama',
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Rule.init(
|
Rule_penyakit.init(
|
||||||
{
|
{
|
||||||
id_gejala: {
|
id_gejala: {
|
||||||
type: DataTypes.INTEGER,
|
type: DataTypes.INTEGER,
|
||||||
|
@ -47,24 +42,16 @@ Rule.init(
|
||||||
key: 'id', // Mengacu ke kolom 'id' pada tabel 'penyakit'
|
key: 'id', // Mengacu ke kolom 'id' pada tabel 'penyakit'
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
id_hama: {
|
|
||||||
type: DataTypes.INTEGER,
|
|
||||||
allowNull: true,
|
|
||||||
references: {
|
|
||||||
model: 'hama', // Mengacu ke tabel 'hama'
|
|
||||||
key: 'id', // Mengacu ke kolom 'id' pada tabel 'hama'
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
sequelize,
|
sequelize,
|
||||||
modelName: 'Rule',
|
modelName: 'Rule_penyakit',
|
||||||
tableName: 'rules',
|
tableName: 'rules_penyakit',
|
||||||
timestamps: false,
|
timestamps: false,
|
||||||
paranoid: false,
|
paranoid: false,
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
return Rule;
|
return Rule_penyakit;
|
||||||
|
|
||||||
}
|
}
|
|
@ -1,5 +1,5 @@
|
||||||
const { Model, DataTypes } = require('sequelize');
|
const { Model, DataTypes } = require('sequelize');
|
||||||
|
const sequelize = require('../config/database');
|
||||||
|
|
||||||
module.exports = (sequelize) => {
|
module.exports = (sequelize) => {
|
||||||
class User extends Model {}
|
class User extends Model {}
|
||||||
|
|
|
@ -0,0 +1,119 @@
|
||||||
|
const express = require('express');
|
||||||
|
const router = express.Router();
|
||||||
|
const ruleController = require('../controller/rulesHamaController');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @swagger
|
||||||
|
* tags:
|
||||||
|
* name: Rules_hama
|
||||||
|
* description: API untuk mengelola aturan (rules)
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @swagger
|
||||||
|
* /api/rules_hama:
|
||||||
|
* post:
|
||||||
|
* summary: Membuat aturan baru
|
||||||
|
* tags: [Rules_hama]
|
||||||
|
* requestBody:
|
||||||
|
* required: true
|
||||||
|
* content:
|
||||||
|
* application/json:
|
||||||
|
* schema:
|
||||||
|
* type: object
|
||||||
|
* required:
|
||||||
|
* - id_gejala
|
||||||
|
* - nilai_pakar
|
||||||
|
* properties:
|
||||||
|
* id_gejala:
|
||||||
|
* type: integer
|
||||||
|
* id_hama:
|
||||||
|
* type: integer
|
||||||
|
* nilai_pakar:
|
||||||
|
* type: number
|
||||||
|
* format: float
|
||||||
|
* responses:
|
||||||
|
* 201:
|
||||||
|
* description: Rule berhasil dibuat
|
||||||
|
* 400:
|
||||||
|
* description: Data tidak lengkap
|
||||||
|
* 500:
|
||||||
|
* description: Terjadi kesalahan server
|
||||||
|
*/
|
||||||
|
router.post('/', ruleController.createRuleHama);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @swagger
|
||||||
|
* /api/rules_hama:
|
||||||
|
* get:
|
||||||
|
* summary: Menampilkan semua aturan
|
||||||
|
* tags: [Rules_hama]
|
||||||
|
* responses:
|
||||||
|
* 200:
|
||||||
|
* description: Daftar rules berhasil diambil
|
||||||
|
* 500:
|
||||||
|
* description: Terjadi kesalahan server
|
||||||
|
*/
|
||||||
|
router.get('/', ruleController.getRulesHama);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @swagger
|
||||||
|
* /api/rules_hama/{id}:
|
||||||
|
* put:
|
||||||
|
* summary: Memperbarui aturan berdasarkan ID
|
||||||
|
* tags: [Rules_hama]
|
||||||
|
* parameters:
|
||||||
|
* - in: path
|
||||||
|
* name: id
|
||||||
|
* required: true
|
||||||
|
* description: ID rule yang ingin diperbarui
|
||||||
|
* schema:
|
||||||
|
* type: integer
|
||||||
|
* requestBody:
|
||||||
|
* required: true
|
||||||
|
* content:
|
||||||
|
* application/json:
|
||||||
|
* schema:
|
||||||
|
* type: object
|
||||||
|
* properties:
|
||||||
|
* id_gejala:
|
||||||
|
* type: integer
|
||||||
|
* id_hama:
|
||||||
|
* type: integer
|
||||||
|
* nilai_pakar:
|
||||||
|
* type: number
|
||||||
|
* format: float
|
||||||
|
* responses:
|
||||||
|
* 200:
|
||||||
|
* description: Rule berhasil diperbarui
|
||||||
|
* 404:
|
||||||
|
* description: Rule tidak ditemukan
|
||||||
|
* 500:
|
||||||
|
* description: Terjadi kesalahan server
|
||||||
|
*/
|
||||||
|
router.put('/:id', ruleController.updateRuleHama);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @swagger
|
||||||
|
* /api/rules_hama/{id}:
|
||||||
|
* delete:
|
||||||
|
* summary: Menghapus aturan berdasarkan ID
|
||||||
|
* tags: [Rules_hama]
|
||||||
|
* parameters:
|
||||||
|
* - in: path
|
||||||
|
* name: id
|
||||||
|
* required: true
|
||||||
|
* description: ID rule yang ingin dihapus
|
||||||
|
* schema:
|
||||||
|
* type: integer
|
||||||
|
* responses:
|
||||||
|
* 200:
|
||||||
|
* description: Rule berhasil dihapus
|
||||||
|
* 404:
|
||||||
|
* description: Rule tidak ditemukan
|
||||||
|
* 500:
|
||||||
|
* description: Terjadi kesalahan server
|
||||||
|
*/
|
||||||
|
router.delete('/:id', ruleController.deleteRuleHama);
|
||||||
|
|
||||||
|
module.exports = router;
|
|
@ -5,16 +5,16 @@ const ruleController = require('../controller/rulesController');
|
||||||
/**
|
/**
|
||||||
* @swagger
|
* @swagger
|
||||||
* tags:
|
* tags:
|
||||||
* name: Rules
|
* name: Rules_penyakit
|
||||||
* description: API untuk mengelola aturan (rules)
|
* description: API untuk mengelola aturan (rules)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @swagger
|
* @swagger
|
||||||
* /api/rules:
|
* /api/rules_penyakit:
|
||||||
* post:
|
* post:
|
||||||
* summary: Membuat aturan baru
|
* summary: Membuat aturan baru
|
||||||
* tags: [Rules]
|
* tags: [Rules_penyakit]
|
||||||
* requestBody:
|
* requestBody:
|
||||||
* required: true
|
* required: true
|
||||||
* content:
|
* content:
|
||||||
|
@ -29,8 +29,6 @@ const ruleController = require('../controller/rulesController');
|
||||||
* type: integer
|
* type: integer
|
||||||
* id_penyakit:
|
* id_penyakit:
|
||||||
* type: integer
|
* type: integer
|
||||||
* id_hama:
|
|
||||||
* type: integer
|
|
||||||
* nilai_pakar:
|
* nilai_pakar:
|
||||||
* type: number
|
* type: number
|
||||||
* format: float
|
* format: float
|
||||||
|
@ -42,28 +40,28 @@ const ruleController = require('../controller/rulesController');
|
||||||
* 500:
|
* 500:
|
||||||
* description: Terjadi kesalahan server
|
* description: Terjadi kesalahan server
|
||||||
*/
|
*/
|
||||||
router.post('/', ruleController.createRule);
|
router.post('/', ruleController.createRulePenyakit);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @swagger
|
* @swagger
|
||||||
* /api/rules:
|
* /api/rules_penyakit:
|
||||||
* get:
|
* get:
|
||||||
* summary: Menampilkan semua aturan
|
* summary: Menampilkan semua aturan
|
||||||
* tags: [Rules]
|
* tags: [Rules_penyakit]
|
||||||
* responses:
|
* responses:
|
||||||
* 200:
|
* 200:
|
||||||
* description: Daftar rules berhasil diambil
|
* description: Daftar rules berhasil diambil
|
||||||
* 500:
|
* 500:
|
||||||
* description: Terjadi kesalahan server
|
* description: Terjadi kesalahan server
|
||||||
*/
|
*/
|
||||||
router.get('/', ruleController.getRules);
|
router.get('/', ruleController.getRulesPenyakit);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @swagger
|
* @swagger
|
||||||
* /api/rules/{id}:
|
* /api/rules_penyakit/{id}:
|
||||||
* put:
|
* put:
|
||||||
* summary: Memperbarui aturan berdasarkan ID
|
* summary: Memperbarui aturan berdasarkan ID
|
||||||
* tags: [Rules]
|
* tags: [Rules_penyakit]
|
||||||
* parameters:
|
* parameters:
|
||||||
* - in: path
|
* - in: path
|
||||||
* name: id
|
* name: id
|
||||||
|
@ -82,8 +80,6 @@ router.get('/', ruleController.getRules);
|
||||||
* type: integer
|
* type: integer
|
||||||
* id_penyakit:
|
* id_penyakit:
|
||||||
* type: integer
|
* type: integer
|
||||||
* id_hama:
|
|
||||||
* type: integer
|
|
||||||
* nilai_pakar:
|
* nilai_pakar:
|
||||||
* type: number
|
* type: number
|
||||||
* format: float
|
* format: float
|
||||||
|
@ -95,14 +91,14 @@ router.get('/', ruleController.getRules);
|
||||||
* 500:
|
* 500:
|
||||||
* description: Terjadi kesalahan server
|
* description: Terjadi kesalahan server
|
||||||
*/
|
*/
|
||||||
router.put('/:id', ruleController.updateRule);
|
router.put('/:id', ruleController.updateRulePenyakit);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @swagger
|
* @swagger
|
||||||
* /api/rules/{id}:
|
* /api/rules_penyakit/{id}:
|
||||||
* delete:
|
* delete:
|
||||||
* summary: Menghapus aturan berdasarkan ID
|
* summary: Menghapus aturan berdasarkan ID
|
||||||
* tags: [Rules]
|
* tags: [Rules_penyakit]
|
||||||
* parameters:
|
* parameters:
|
||||||
* - in: path
|
* - in: path
|
||||||
* name: id
|
* name: id
|
||||||
|
@ -118,6 +114,6 @@ router.put('/:id', ruleController.updateRule);
|
||||||
* 500:
|
* 500:
|
||||||
* description: Terjadi kesalahan server
|
* description: Terjadi kesalahan server
|
||||||
*/
|
*/
|
||||||
router.delete('/:id', ruleController.deleteRule);
|
router.delete('/:id', ruleController.deleteRulePenyakit);
|
||||||
|
|
||||||
module.exports = router;
|
module.exports = router;
|
||||||
|
|
|
@ -2,6 +2,7 @@ import 'package:flutter/material.dart';
|
||||||
import 'hama_page.dart';
|
import 'hama_page.dart';
|
||||||
import 'penyakit_page.dart';
|
import 'penyakit_page.dart';
|
||||||
import 'gejala_page.dart';
|
import 'gejala_page.dart';
|
||||||
|
import 'rule_page.dart';
|
||||||
import 'package:frontend/api_services/api_services.dart';
|
import 'package:frontend/api_services/api_services.dart';
|
||||||
import 'package:frontend/user/login_page.dart';
|
import 'package:frontend/user/login_page.dart';
|
||||||
|
|
||||||
|
@ -62,6 +63,15 @@ class AdminPage extends StatelessWidget {
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
ListTile(
|
||||||
|
title: Text('Halaman Aturan'),
|
||||||
|
onTap: () {
|
||||||
|
Navigator.push(
|
||||||
|
context,
|
||||||
|
MaterialPageRoute(builder: (context) => RulePage()),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
ListTile(title: Text('Logout'), onTap: () => _logout(context)),
|
ListTile(title: Text('Logout'), onTap: () => _logout(context)),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
|
|
@ -68,134 +68,6 @@ class _PenyakitPageState extends State<PenyakitPage> {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// void _tambahPenyakit() {
|
|
||||||
// TextEditingController namaController = TextEditingController();
|
|
||||||
// TextEditingController penangananController = TextEditingController();
|
|
||||||
// TextEditingController deskripsiController = TextEditingController();
|
|
||||||
|
|
||||||
// showDialog(
|
|
||||||
// context: context,
|
|
||||||
// builder: (context) {
|
|
||||||
// return AlertDialog(
|
|
||||||
// title: Text('Tambah Penyakit Baru'),
|
|
||||||
// content: Column(
|
|
||||||
// mainAxisSize: MainAxisSize.min,
|
|
||||||
// children: [
|
|
||||||
// TextField(
|
|
||||||
// controller: namaController,
|
|
||||||
// decoration: InputDecoration(labelText: 'Nama'),
|
|
||||||
// ),
|
|
||||||
// TextField(
|
|
||||||
// controller: deskripsiController,
|
|
||||||
// decoration: InputDecoration(labelText: 'Deskripsi'),
|
|
||||||
// ),
|
|
||||||
// TextField(
|
|
||||||
// controller: penangananController,
|
|
||||||
// decoration: InputDecoration(labelText: 'Penanganan'),
|
|
||||||
// ),
|
|
||||||
// ],
|
|
||||||
// ),
|
|
||||||
// actions: [
|
|
||||||
// TextButton(
|
|
||||||
// onPressed: () => Navigator.pop(context),
|
|
||||||
// child: Text('Batal'),
|
|
||||||
// ),
|
|
||||||
// ElevatedButton(
|
|
||||||
// onPressed: () async {
|
|
||||||
// if (namaController.text.isNotEmpty &&
|
|
||||||
// deskripsiController.text.isNotEmpty &&
|
|
||||||
// penangananController.text.isNotEmpty) {
|
|
||||||
// try {
|
|
||||||
// await apiService.createPenyakit(
|
|
||||||
// namaController.text,
|
|
||||||
// deskripsiController.text,
|
|
||||||
// penangananController.text,
|
|
||||||
// );
|
|
||||||
// _fetchPenyakit();
|
|
||||||
// Navigator.pop(context);
|
|
||||||
// } catch (e) {
|
|
||||||
// print("Error adding penyakit: $e");
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// },
|
|
||||||
// child: Text('Simpan'),
|
|
||||||
// ),
|
|
||||||
// ],
|
|
||||||
// );
|
|
||||||
// },
|
|
||||||
// ).then((_) {
|
|
||||||
// namaController.dispose();
|
|
||||||
// deskripsiController.dispose();
|
|
||||||
// penangananController.dispose();
|
|
||||||
// });
|
|
||||||
// }
|
|
||||||
|
|
||||||
// void showEditDialog(BuildContext context, Map<String, dynamic> penyakit) {
|
|
||||||
// final TextEditingController editNamaController = TextEditingController(text: penyakit['nama'] ?? '');
|
|
||||||
// final TextEditingController editDeskripsiController = TextEditingController(text: penyakit['deskripsi'] ?? '');
|
|
||||||
// final TextEditingController editPenangananController = TextEditingController(text: penyakit['penanganan'] ?? '');
|
|
||||||
|
|
||||||
// showDialog(
|
|
||||||
// context: context,
|
|
||||||
// builder: (context) {
|
|
||||||
// return AlertDialog(
|
|
||||||
// title: Text(
|
|
||||||
// 'Edit Penyakit',
|
|
||||||
// ),
|
|
||||||
// content: Column(
|
|
||||||
// mainAxisSize: MainAxisSize.min,
|
|
||||||
// children: [
|
|
||||||
// TextField(
|
|
||||||
// controller: editNamaController,
|
|
||||||
// decoration: InputDecoration(
|
|
||||||
// labelText: 'Nama',
|
|
||||||
// ),
|
|
||||||
// ),
|
|
||||||
// TextField(
|
|
||||||
// controller: editDeskripsiController,
|
|
||||||
// decoration: InputDecoration(
|
|
||||||
// labelText: 'Deskripsi',
|
|
||||||
// ),
|
|
||||||
// ),
|
|
||||||
// TextField(
|
|
||||||
// controller: editPenangananController,
|
|
||||||
// decoration: InputDecoration(
|
|
||||||
// labelText: 'Penanganan',
|
|
||||||
// ),
|
|
||||||
// ),
|
|
||||||
// ],
|
|
||||||
// ),
|
|
||||||
// actions: [
|
|
||||||
// TextButton(
|
|
||||||
// onPressed: () => Navigator.pop(context),
|
|
||||||
// child: Text(
|
|
||||||
// 'Batal',
|
|
||||||
// style: TextStyle(color: Colors.black),
|
|
||||||
// ),
|
|
||||||
// ),
|
|
||||||
// ElevatedButton(
|
|
||||||
// onPressed: () async {
|
|
||||||
// try {
|
|
||||||
// await apiService.updatePenyakit(
|
|
||||||
// penyakit['id'],
|
|
||||||
// editNamaController.text,
|
|
||||||
// editDeskripsiController.text,
|
|
||||||
// editPenangananController.text,
|
|
||||||
// );
|
|
||||||
// _fetchPenyakit();
|
|
||||||
// Navigator.pop(context);
|
|
||||||
// } catch (e) {
|
|
||||||
// print("Error updating penyakit: $e");
|
|
||||||
// }
|
|
||||||
// },
|
|
||||||
// child: Text('Simpan', style: TextStyle(color: Colors.black)),
|
|
||||||
// ),
|
|
||||||
// ],
|
|
||||||
// );
|
|
||||||
// },
|
|
||||||
// );
|
|
||||||
// }
|
|
||||||
|
|
||||||
//pagination
|
//pagination
|
||||||
int currentPage = 0;
|
int currentPage = 0;
|
||||||
int rowsPerPage = 10;
|
int rowsPerPage = 10;
|
||||||
|
|
|
@ -0,0 +1,294 @@
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:http/http.dart' as http;
|
||||||
|
import 'package:frontend/api_services/api_services.dart';
|
||||||
|
import 'tambah_rule_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;
|
||||||
|
|
||||||
|
@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'], // Menambahkan nilai_pakar dari rule_penyakit
|
||||||
|
};
|
||||||
|
}),
|
||||||
|
// Mengolah rules hama
|
||||||
|
...rulesHama.map((rule) {
|
||||||
|
print(
|
||||||
|
"Rule id_gejala: ${rule['id_gejala']}, id_hama: ${rule['id_hama']}",
|
||||||
|
);
|
||||||
|
|
||||||
|
// Mencari gejala berdasarkan id
|
||||||
|
final gejala = gejalaList.firstWhere((item) {
|
||||||
|
print(
|
||||||
|
"Mencocokkan gejala id: ${item['id']} dengan ${rule['id_gejala']}",
|
||||||
|
);
|
||||||
|
return 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'},
|
||||||
|
);
|
||||||
|
|
||||||
|
print(
|
||||||
|
"Gejala ditemukan: ${gejala['nama']}, Hama ditemukan: ${hama['nama']}",
|
||||||
|
);
|
||||||
|
|
||||||
|
// Menampilkan isi dari gejalaList dan hamaList untuk debugging
|
||||||
|
print("Isi gejalaList:");
|
||||||
|
for (var item in gejalaList) {
|
||||||
|
print(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
print("Isi hamaList:");
|
||||||
|
for (var item in hamaList) {
|
||||||
|
print(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
'id': rule['id'],
|
||||||
|
'id_gejala': rule['id_gejala'],
|
||||||
|
'id_penyakit': null,
|
||||||
|
'id_hama': rule['id_hama'],
|
||||||
|
'nama_gejala': gejala['nama'], // Memastikan nama gejala ditampilkan
|
||||||
|
'nama_penyakit': null,
|
||||||
|
'nama_hama': hama['nama'], // Memastikan nama hama ditampilkan
|
||||||
|
'nilai_pakar':
|
||||||
|
rule['nilai_pakar'], // Menambahkan nilai_pakar dari rule_hama
|
||||||
|
};
|
||||||
|
}),
|
||||||
|
];
|
||||||
|
|
||||||
|
setState(() {
|
||||||
|
rules = enrichedRules;
|
||||||
|
});
|
||||||
|
} catch (e) {
|
||||||
|
print('Terjadi kesalahan saat memuat data: $e');
|
||||||
|
for (var rule in rules) {
|
||||||
|
print("Mencari gejala untuk id_gejala: ${rule['id_gejala']}");
|
||||||
|
var gejala = gejalaList.firstWhere(
|
||||||
|
(item) => item['id'].toString() == rule['id_gejala'].toString(),
|
||||||
|
orElse: () => {'nama': 'TIDAK DITEMUKAN'},
|
||||||
|
);
|
||||||
|
print("Gejala ditemukan: ${gejala['nama']}");
|
||||||
|
}
|
||||||
|
} 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")),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@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: [
|
||||||
|
Align(
|
||||||
|
alignment: Alignment.centerRight,
|
||||||
|
child: ElevatedButton.icon(
|
||||||
|
onPressed: () {
|
||||||
|
Navigator.push(
|
||||||
|
context,
|
||||||
|
MaterialPageRoute(
|
||||||
|
builder:
|
||||||
|
(context) => TambahRulePage(
|
||||||
|
isEditing: false, // Menandakan mode tambah
|
||||||
|
isEditingHama:
|
||||||
|
true, // Atur sesuai dengan jenis rule
|
||||||
|
selectedRuleIds: [],
|
||||||
|
selectedGejalaIds: [],
|
||||||
|
nilaiPakarList: [],
|
||||||
|
selectedHamaId: null, // Hanya jika rule hama
|
||||||
|
selectedPenyakitId:
|
||||||
|
null, // Hanya jika rule penyakit
|
||||||
|
),
|
||||||
|
),
|
||||||
|
).then((_) => fetchRules());
|
||||||
|
},
|
||||||
|
icon: Icon(Icons.add),
|
||||||
|
label: Text("Tambah Rule"),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(height: 16),
|
||||||
|
isLoading
|
||||||
|
? const Center(child: CircularProgressIndicator())
|
||||||
|
: Expanded(
|
||||||
|
child: SingleChildScrollView(
|
||||||
|
scrollDirection: Axis.horizontal,
|
||||||
|
child: DataTable(
|
||||||
|
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(rules.length, (index) {
|
||||||
|
final rule = rules[index];
|
||||||
|
|
||||||
|
final namaKategori =
|
||||||
|
rule['id_penyakit'] != null
|
||||||
|
? rule['nama_penyakit'] ?? '-'
|
||||||
|
: rule['nama_hama'] ?? '-';
|
||||||
|
|
||||||
|
final isPenyakit = rule['id_penyakit'] != null;
|
||||||
|
|
||||||
|
return DataRow(
|
||||||
|
cells: [
|
||||||
|
DataCell(Text((index + 1).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) {
|
||||||
|
Navigator.push(
|
||||||
|
context,
|
||||||
|
MaterialPageRoute(
|
||||||
|
builder:
|
||||||
|
(context) => TambahRulePage(
|
||||||
|
isEditing: true,
|
||||||
|
isEditingHama: true,
|
||||||
|
selectedRuleIds: [rule.id],
|
||||||
|
selectedGejalaIds: [
|
||||||
|
rule.idGejala,
|
||||||
|
],
|
||||||
|
nilaiPakarList: [
|
||||||
|
rule.nilaiPakar,
|
||||||
|
],
|
||||||
|
selectedHamaId: rule.idHama,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
print(
|
||||||
|
'Data rule tidak lengkap atau null',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
),
|
||||||
|
|
||||||
|
IconButton(
|
||||||
|
icon: const Icon(
|
||||||
|
Icons.delete,
|
||||||
|
color: Colors.red,
|
||||||
|
),
|
||||||
|
onPressed: () {
|
||||||
|
deleteRule(rule);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,403 @@
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:frontend/api_services/api_services.dart';
|
||||||
|
import 'package:http/http.dart' as http;
|
||||||
|
|
||||||
|
class TambahRulePage extends StatefulWidget {
|
||||||
|
@override
|
||||||
|
_TambahRulePageState createState() => _TambahRulePageState();
|
||||||
|
|
||||||
|
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 TambahRulePage({
|
||||||
|
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 _TambahRulePageState extends State<TambahRulePage> {
|
||||||
|
|
||||||
|
int? selectedHamaId;
|
||||||
|
int? selectedPenyakitId;
|
||||||
|
List<int?> selectedGejalaIds = [null];
|
||||||
|
List<double> nilaiPakarList = [0.5];
|
||||||
|
List<int?> selectedRuleIds = []; // List paralel dengan selectedGejalaIds dan nilaiPakarList
|
||||||
|
|
||||||
|
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();
|
||||||
|
|
||||||
|
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")),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// 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
|
||||||
|
}
|
||||||
|
|
||||||
|
void saveRules() 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 idGejala = selectedGejalaIds[i];
|
||||||
|
final nilai = nilaiPakarList[i];
|
||||||
|
|
||||||
|
if (idGejala != null) {
|
||||||
|
if (selectedPenyakitId != null) {
|
||||||
|
final response = await ApiService.createRulePenyakit(
|
||||||
|
idGejala: idGejala,
|
||||||
|
idPenyakit: selectedPenyakitId,
|
||||||
|
nilaiPakar: nilai,
|
||||||
|
);
|
||||||
|
|
||||||
|
if (response.statusCode != 200 && response.statusCode != 201) {
|
||||||
|
throw Exception("Gagal menyimpan rule penyakit");
|
||||||
|
}
|
||||||
|
} else if (selectedHamaId != null) {
|
||||||
|
final response = await ApiService.createRuleHama(
|
||||||
|
idGejala: idGejala,
|
||||||
|
idHama: selectedHamaId,
|
||||||
|
nilaiPakar: nilai,
|
||||||
|
);
|
||||||
|
|
||||||
|
if (response.statusCode != 200 && response.statusCode != 201) {
|
||||||
|
throw Exception("Gagal menyimpan rule hama");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ScaffoldMessenger.of(
|
||||||
|
context,
|
||||||
|
).showSnackBar(SnackBar(content: Text("Data berhasil disimpan")));
|
||||||
|
|
||||||
|
Navigator.pop(context);
|
||||||
|
} catch (e) {
|
||||||
|
print('Gagal menyimpan data: $e');
|
||||||
|
ScaffoldMessenger.of(
|
||||||
|
context,
|
||||||
|
).showSnackBar(SnackBar(content: Text("Gagal menyimpan data")));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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];
|
||||||
|
|
||||||
|
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 (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,
|
||||||
|
decoration: InputDecoration(
|
||||||
|
labelText: "Nilai Pakar",
|
||||||
|
border: OutlineInputBorder(),
|
||||||
|
),
|
||||||
|
onChanged: (value) {
|
||||||
|
setState(() {
|
||||||
|
if (value.isNotEmpty) {
|
||||||
|
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 menambah rule
|
||||||
|
ElevatedButton(
|
||||||
|
onPressed: () {
|
||||||
|
// Panggil fungsi saveRules untuk menyimpan data
|
||||||
|
saveRules();
|
||||||
|
},
|
||||||
|
child: Text('Tambah Rule'),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -7,9 +7,15 @@ class ApiService {
|
||||||
static const String gejalaUrl = 'http://localhost:5000/api/gejala';
|
static const String gejalaUrl = 'http://localhost:5000/api/gejala';
|
||||||
static const String hamaUrl = 'http://localhost:5000/api/hama';
|
static const String hamaUrl = 'http://localhost:5000/api/hama';
|
||||||
static const String penyakitUrl = 'http://localhost:5000/api/penyakit';
|
static const String penyakitUrl = 'http://localhost:5000/api/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)
|
// Fungsi Login (dengan perbaikan)
|
||||||
static Future<Map<String, dynamic>> loginUser(String email, String password) async {
|
static Future<Map<String, dynamic>> loginUser(
|
||||||
|
String email,
|
||||||
|
String password,
|
||||||
|
) async {
|
||||||
try {
|
try {
|
||||||
final response = await http.post(
|
final response = await http.post(
|
||||||
Uri.parse("$baseUrl/login"),
|
Uri.parse("$baseUrl/login"),
|
||||||
|
@ -114,31 +120,38 @@ class ApiService {
|
||||||
|
|
||||||
// Ambil semua hama
|
// Ambil semua hama
|
||||||
Future<List<Map<String, dynamic>>> getHama() async {
|
Future<List<Map<String, dynamic>>> getHama() async {
|
||||||
try {
|
try {
|
||||||
final response = await http.get(Uri.parse(ApiService.hamaUrl));
|
final response = await http.get(Uri.parse(ApiService.hamaUrl));
|
||||||
|
|
||||||
if (response.statusCode == 200) {
|
if (response.statusCode == 200) {
|
||||||
final responseData = jsonDecode(response.body);
|
final responseData = jsonDecode(response.body);
|
||||||
|
|
||||||
// Pastikan "data" ada dan berupa List
|
// Pastikan "data" ada dan berupa List
|
||||||
if (responseData is Map<String, dynamic> && responseData.containsKey("data")) {
|
if (responseData is Map<String, dynamic> &&
|
||||||
final List<dynamic> data = responseData["data"];
|
responseData.containsKey("data")) {
|
||||||
|
final List<dynamic> data = responseData["data"];
|
||||||
|
|
||||||
return List<Map<String, dynamic>>.from(data.map((item) => Map<String, dynamic>.from(item)));
|
return List<Map<String, dynamic>>.from(
|
||||||
|
data.map((item) => Map<String, dynamic>.from(item)),
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
throw Exception("Format respons API tidak sesuai");
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
throw Exception("Format respons API tidak sesuai");
|
throw Exception("Gagal mengambil data hama");
|
||||||
}
|
}
|
||||||
} else {
|
} catch (e) {
|
||||||
|
print("Error getHama: $e");
|
||||||
throw Exception("Gagal mengambil data hama");
|
throw Exception("Gagal mengambil data hama");
|
||||||
}
|
}
|
||||||
} catch (e) {
|
|
||||||
print("Error getHama: $e");
|
|
||||||
throw Exception("Gagal mengambil data hama");
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Tambah hama baru (kode otomatis)
|
// Tambah hama baru (kode otomatis)
|
||||||
Future<Map<String, dynamic>> createHama(String nama, String deskripsi, String penanganan) async {
|
Future<Map<String, dynamic>> createHama(
|
||||||
|
String nama,
|
||||||
|
String deskripsi,
|
||||||
|
String penanganan,
|
||||||
|
) async {
|
||||||
try {
|
try {
|
||||||
final response = await http.post(
|
final response = await http.post(
|
||||||
Uri.parse(hamaUrl),
|
Uri.parse(hamaUrl),
|
||||||
|
@ -146,7 +159,7 @@ class ApiService {
|
||||||
body: jsonEncode({
|
body: jsonEncode({
|
||||||
"nama": nama,
|
"nama": nama,
|
||||||
"deskripsi": deskripsi,
|
"deskripsi": deskripsi,
|
||||||
"penanganan": penanganan
|
"penanganan": penanganan,
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -161,15 +174,21 @@ class ApiService {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update hama berdasarkan ID
|
// Update hama berdasarkan ID
|
||||||
Future<Map<String, dynamic>> updateHama(int id, String nama, String deskripsi, String penanganan) async {
|
Future<Map<String, dynamic>> updateHama(
|
||||||
|
int id,
|
||||||
|
String nama,
|
||||||
|
String deskripsi,
|
||||||
|
String penanganan,
|
||||||
|
) async {
|
||||||
try {
|
try {
|
||||||
final response = await http.put(Uri.parse('$hamaUrl/$id'),
|
final response = await http.put(
|
||||||
|
Uri.parse('$hamaUrl/$id'),
|
||||||
headers: {"Content-Type": "application/json"},
|
headers: {"Content-Type": "application/json"},
|
||||||
body: jsonEncode({
|
body: jsonEncode({
|
||||||
"nama": nama,
|
"nama": nama,
|
||||||
"deskripsi": deskripsi,
|
"deskripsi": deskripsi,
|
||||||
"penanganan": penanganan
|
"penanganan": penanganan,
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -199,31 +218,38 @@ class ApiService {
|
||||||
|
|
||||||
// Ambil semua penyakit
|
// Ambil semua penyakit
|
||||||
Future<List<Map<String, dynamic>>> getPenyakit() async {
|
Future<List<Map<String, dynamic>>> getPenyakit() async {
|
||||||
try {
|
try {
|
||||||
final response = await http.get(Uri.parse(ApiService.penyakitUrl));
|
final response = await http.get(Uri.parse(ApiService.penyakitUrl));
|
||||||
|
|
||||||
if (response.statusCode == 200) {
|
if (response.statusCode == 200) {
|
||||||
final responseData = jsonDecode(response.body);
|
final responseData = jsonDecode(response.body);
|
||||||
|
|
||||||
// Pastikan "data" ada dan berupa List
|
// Pastikan "data" ada dan berupa List
|
||||||
if (responseData is Map<String, dynamic> && responseData.containsKey("data")) {
|
if (responseData is Map<String, dynamic> &&
|
||||||
final List<dynamic> data = responseData["data"];
|
responseData.containsKey("data")) {
|
||||||
|
final List<dynamic> data = responseData["data"];
|
||||||
|
|
||||||
return List<Map<String, dynamic>>.from(data.map((item) => Map<String, dynamic>.from(item)));
|
return List<Map<String, dynamic>>.from(
|
||||||
|
data.map((item) => Map<String, dynamic>.from(item)),
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
throw Exception("Format respons API tidak sesuai");
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
throw Exception("Format respons API tidak sesuai");
|
throw Exception("Gagal mengambil data penyakit");
|
||||||
}
|
}
|
||||||
} else {
|
} catch (e) {
|
||||||
|
print("Error getHama: $e");
|
||||||
throw Exception("Gagal mengambil data penyakit");
|
throw Exception("Gagal mengambil data penyakit");
|
||||||
}
|
}
|
||||||
} catch (e) {
|
|
||||||
print("Error getHama: $e");
|
|
||||||
throw Exception("Gagal mengambil data penyakit");
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Tambah penyakit baru (kode otomatis)
|
// Tambah penyakit baru (kode otomatis)
|
||||||
Future<Map<String, dynamic>> createPenyakit(String nama, String deskripsi, String penanganan) async {
|
Future<Map<String, dynamic>> createPenyakit(
|
||||||
|
String nama,
|
||||||
|
String deskripsi,
|
||||||
|
String penanganan,
|
||||||
|
) async {
|
||||||
try {
|
try {
|
||||||
final response = await http.post(
|
final response = await http.post(
|
||||||
Uri.parse(penyakitUrl),
|
Uri.parse(penyakitUrl),
|
||||||
|
@ -231,7 +257,7 @@ class ApiService {
|
||||||
body: jsonEncode({
|
body: jsonEncode({
|
||||||
"nama": nama,
|
"nama": nama,
|
||||||
"deskripsi": deskripsi,
|
"deskripsi": deskripsi,
|
||||||
"penanganan": penanganan
|
"penanganan": penanganan,
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -246,15 +272,21 @@ class ApiService {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update penyakit berdasarkan ID
|
// Update penyakit berdasarkan ID
|
||||||
Future<Map<String, dynamic>> updatePenyakit(int id, String nama, String deskripsi, String penanganan) async {
|
Future<Map<String, dynamic>> updatePenyakit(
|
||||||
|
int id,
|
||||||
|
String nama,
|
||||||
|
String deskripsi,
|
||||||
|
String penanganan,
|
||||||
|
) async {
|
||||||
try {
|
try {
|
||||||
final response = await http.put(Uri.parse('$penyakitUrl/$id'),
|
final response = await http.put(
|
||||||
|
Uri.parse('$penyakitUrl/$id'),
|
||||||
headers: {"Content-Type": "application/json"},
|
headers: {"Content-Type": "application/json"},
|
||||||
body: jsonEncode({
|
body: jsonEncode({
|
||||||
"nama": nama,
|
"nama": nama,
|
||||||
"deskripsi": deskripsi,
|
"deskripsi": deskripsi,
|
||||||
"penanganan": penanganan
|
"penanganan": penanganan,
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -304,7 +336,9 @@ class ApiService {
|
||||||
);
|
);
|
||||||
|
|
||||||
if (response.statusCode != 201) {
|
if (response.statusCode != 201) {
|
||||||
throw Exception(jsonDecode(response.body)['message'] ?? 'Gagal mendaftar');
|
throw Exception(
|
||||||
|
jsonDecode(response.body)['message'] ?? 'Gagal mendaftar',
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -323,9 +357,151 @@ class ApiService {
|
||||||
);
|
);
|
||||||
|
|
||||||
if (response.statusCode != 200) {
|
if (response.statusCode != 200) {
|
||||||
throw Exception(jsonDecode(response.body)['message'] ?? 'Gagal memperbarui password');
|
throw Exception(
|
||||||
|
jsonDecode(response.body)['message'] ?? 'Gagal memperbarui password',
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
// Create Rule penyakit
|
||||||
|
static Future<http.Response> createRulePenyakit({
|
||||||
|
required int idGejala,
|
||||||
|
int? idPenyakit,
|
||||||
|
required double nilaiPakar,
|
||||||
|
}) async {
|
||||||
|
final response = await http.post(
|
||||||
|
Uri.parse('$rulesPenyakitUrl'),
|
||||||
|
headers: {'Content-Type': 'application/json'},
|
||||||
|
body: jsonEncode({
|
||||||
|
'id_gejala': idGejala,
|
||||||
|
'id_penyakit': idPenyakit,
|
||||||
|
'nilai_pakar': nilaiPakar,
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
|
||||||
|
//get all rules penyakit
|
||||||
|
Future<List<dynamic>> getRulesPenyakit() async {
|
||||||
|
final response = await http.get(Uri.parse(rulesPenyakitUrl));
|
||||||
|
|
||||||
|
if (response.statusCode == 200) {
|
||||||
|
final data = jsonDecode(response.body);
|
||||||
|
|
||||||
|
if (data['data'] == null) {
|
||||||
|
throw Exception('Data rules kosong');
|
||||||
|
}
|
||||||
|
|
||||||
|
return data['data'];
|
||||||
|
} else {
|
||||||
|
throw Exception('Gagal mengambil data rules: ${response.statusCode}');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update Rule penyakit
|
||||||
|
static Future<http.Response> updateRulePenyakit({
|
||||||
|
required int id,
|
||||||
|
required int idGejala,
|
||||||
|
int? idPenyakit,
|
||||||
|
required double nilaiPakar,
|
||||||
|
}) async {
|
||||||
|
final response = await http.put(
|
||||||
|
Uri.parse('$rulesPenyakitUrl/$id'),
|
||||||
|
headers: {'Content-Type': 'application/json'},
|
||||||
|
body: jsonEncode({
|
||||||
|
'id_gejala': idGejala,
|
||||||
|
'id_penyakit': idPenyakit,
|
||||||
|
'nilai_pakar': nilaiPakar,
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Delete Rule penyakit
|
||||||
|
static Future<http.Response> deleteRulePenyakit(int id) async {
|
||||||
|
final response = await http.delete(
|
||||||
|
Uri.parse('$rulesPenyakitUrl/$id'),
|
||||||
|
);
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create Rule Hama
|
||||||
|
static Future<http.Response> createRuleHama({
|
||||||
|
required int idGejala,
|
||||||
|
int? idHama,
|
||||||
|
required double nilaiPakar,
|
||||||
|
}) async {
|
||||||
|
try {
|
||||||
|
// Mencetak URL untuk debugging
|
||||||
|
print("URL API: $rulesHamaUrl");
|
||||||
|
|
||||||
|
// Kirim request POST ke server
|
||||||
|
final response = await http.post(
|
||||||
|
Uri.parse('$rulesHamaUrl'),
|
||||||
|
headers: {'Content-Type': 'application/json'},
|
||||||
|
body: jsonEncode({
|
||||||
|
'id_gejala': idGejala,
|
||||||
|
'id_hama': idHama,
|
||||||
|
'nilai_pakar': nilaiPakar,
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
|
// Pengecekan status response
|
||||||
|
if (response.statusCode == 200 || response.statusCode == 201) {
|
||||||
|
// Jika berhasil, kembalikan response
|
||||||
|
return response;
|
||||||
|
} else {
|
||||||
|
// Jika gagal, cetak error dan lempar exception
|
||||||
|
print("Gagal: ${response.statusCode} - ${response.body}");
|
||||||
|
throw Exception('Gagal menyimpan rule hama. ${response.body}');
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
print('Error: $e');
|
||||||
|
rethrow; // Rethrow exception agar bisa ditangani di tempat lain
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//get all rules hama
|
||||||
|
Future<List<dynamic>> getRulesHama() async {
|
||||||
|
final response = await http.get(Uri.parse(rulesHamaUrl));
|
||||||
|
|
||||||
|
if (response.statusCode == 200) {
|
||||||
|
final data = jsonDecode(response.body);
|
||||||
|
|
||||||
|
if (data['data'] == null) {
|
||||||
|
throw Exception('Data rules kosong');
|
||||||
|
}
|
||||||
|
|
||||||
|
return data['data'];
|
||||||
|
} else {
|
||||||
|
throw Exception('Gagal mengambil data rules: ${response.statusCode}');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update Rule hama
|
||||||
|
static Future<http.Response> updateRuleHama({
|
||||||
|
required int id,
|
||||||
|
required int idGejala,
|
||||||
|
int? idHama,
|
||||||
|
required double nilaiPakar,
|
||||||
|
}) async {
|
||||||
|
final response = await http.put(
|
||||||
|
Uri.parse('$rulesHamaUrl/$id'),
|
||||||
|
headers: {'Content-Type': 'application/json'},
|
||||||
|
body: jsonEncode({
|
||||||
|
'id_gejala': idGejala,
|
||||||
|
'id_hama': idHama,
|
||||||
|
'nilai_pakar': nilaiPakar,
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Delete Rule hama
|
||||||
|
static Future<http.Response> deleteRuleHama(int id) async {
|
||||||
|
final response = await http.delete(
|
||||||
|
Uri.parse('$rulesHamaUrl/$id'),
|
||||||
|
);
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue