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 penyakitRoutes = require('./routes/penyakitRoutes');
|
||||
const ruleRoutes = require('./routes/ruleRoutes');
|
||||
const ruleHamaRoutes = require('./routes/ruleHamaRoutes');
|
||||
const swaggerDocs = require('./swagger');
|
||||
|
||||
dotenv.config();
|
||||
|
@ -25,7 +26,8 @@ app.use("/api/auth", authRoutes);
|
|||
app.use("/api/gejala", gejalaRoutes);
|
||||
app.use("/api/hama", hamaRoutes);
|
||||
app.use("/api/penyakit", penyakitRoutes);
|
||||
app.use("/api/rules", ruleRoutes);
|
||||
app.use("/api/rules_penyakit", ruleRoutes);
|
||||
app.use("/api/rules_hama", ruleHamaRoutes);
|
||||
|
||||
|
||||
// Swagger Documentation
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
const jwt = require('jsonwebtoken');
|
||||
const argon2 = require('argon2');
|
||||
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();
|
||||
|
||||
// Fungsi untuk membuat token JWT
|
||||
|
@ -13,7 +13,6 @@ const generateToken = (user) => {
|
|||
);
|
||||
};
|
||||
|
||||
|
||||
// Menambahkan user baru dengan hashing Argon2
|
||||
exports.register = async (req, res) => {
|
||||
try {
|
||||
|
|
|
@ -1,9 +1,11 @@
|
|||
const Gejala = require('../models/gejala');
|
||||
const {Gejala} = require('../models');
|
||||
|
||||
// 🔹 Menampilkan semua data gejala
|
||||
exports.getAllGejala = async (req, res) => {
|
||||
try {
|
||||
const gejala = await Gejala.findAll();
|
||||
const gejala = await Gejala.findAll({
|
||||
attributes: ['id', 'nama']
|
||||
});
|
||||
res.status(200).json(gejala);
|
||||
} catch (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
|
||||
exports.getAllHama = async (req, res) => {
|
||||
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 });
|
||||
} catch (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
|
||||
exports.getAllPenyakit = async (req, res) => {
|
||||
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 });
|
||||
} catch (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
|
||||
exports.createRule = async (req, res) => {
|
||||
exports.createRulePenyakit = async (req, res) => {
|
||||
try {
|
||||
const { id_gejala, id_penyakit, id_hama, nilai_pakar } = req.body;
|
||||
const { id_gejala, id_penyakit, nilai_pakar } = req.body;
|
||||
|
||||
// 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' });
|
||||
}
|
||||
|
||||
const newRule = await Rule.create({
|
||||
const newRule = await Rule_penyakit.create({
|
||||
id_gejala,
|
||||
id_penyakit,
|
||||
id_hama,
|
||||
nilai_pakar
|
||||
});
|
||||
|
||||
|
@ -25,9 +24,9 @@ exports.createRule = async (req, res) => {
|
|||
};
|
||||
|
||||
// 🔥 Ambil semua aturan
|
||||
exports.getRules = async (req, res) => {
|
||||
exports.getRulesPenyakit = async (req, res) => {
|
||||
try {
|
||||
const rules = await Rule.findAll();
|
||||
const rules = await Rule_penyakit.findAll();
|
||||
|
||||
res.status(200).json({ message: 'Daftar Rules', data: rules });
|
||||
} catch (error) {
|
||||
|
@ -37,12 +36,12 @@ exports.getRules = async (req, res) => {
|
|||
};
|
||||
|
||||
// 🔥 Update aturan
|
||||
exports.updateRule = async (req, res) => {
|
||||
exports.updateRulePenyakit = async (req, res) => {
|
||||
try {
|
||||
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) {
|
||||
return res.status(404).json({ message: 'Rule tidak ditemukan' });
|
||||
}
|
||||
|
@ -50,7 +49,6 @@ exports.updateRule = async (req, res) => {
|
|||
await rule.update({
|
||||
id_gejala,
|
||||
id_penyakit,
|
||||
id_hama,
|
||||
nilai_pakar
|
||||
});
|
||||
|
||||
|
@ -62,11 +60,11 @@ exports.updateRule = async (req, res) => {
|
|||
};
|
||||
|
||||
// 🔥 Hapus aturan
|
||||
exports.deleteRule = async (req, res) => {
|
||||
exports.deleteRulePenyakit = async (req, res) => {
|
||||
try {
|
||||
const { id } = req.params;
|
||||
|
||||
const rule = await Rule.findByPk(id);
|
||||
const rule = await Rule_penyakit.findByPk(id);
|
||||
if (!rule) {
|
||||
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 { Op } = require('sequelize');
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
/** @type {import('sequelize-cli').Migration} */
|
||||
module.exports = {
|
||||
async up(queryInterface, Sequelize) {
|
||||
await queryInterface.createTable('Rules', {
|
||||
await queryInterface.createTable('Rules_penyakit', {
|
||||
id: {
|
||||
allowNull: false,
|
||||
autoIncrement: true,
|
||||
|
@ -27,16 +27,9 @@ module.exports = {
|
|||
key:'id'
|
||||
}
|
||||
},
|
||||
id_hama: {
|
||||
type: Sequelize.INTEGER,
|
||||
references:{
|
||||
model: 'hama',
|
||||
key: 'id'
|
||||
}
|
||||
},
|
||||
});
|
||||
},
|
||||
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 sequelize = require('../config/database');
|
||||
|
||||
module.exports = (sequelize) => {
|
||||
class Gejala extends Model {}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
const { Model, DataTypes } = require('sequelize');
|
||||
|
||||
const sequelize = require('../config/database');
|
||||
|
||||
module.exports = (sequelize) => {
|
||||
class Hama extends Model {}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
const { Model, DataTypes } = require('sequelize');
|
||||
|
||||
const sequelize = require('../config/database');
|
||||
|
||||
module.exports =(sequelize) => {
|
||||
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 sequelize = require('../config/database');
|
||||
|
||||
module.exports = (sequelize) => {
|
||||
|
||||
class Rule extends Model {
|
||||
class Rule_penyakit extends Model {
|
||||
static associate(models) {
|
||||
// Asosiasi dengan model Gejala
|
||||
Rule.belongsTo(models.Gejala, {
|
||||
Rule_penyakit.belongsTo(models.Gejala, {
|
||||
foreignKey: 'id_gejala',
|
||||
as: 'gejala', // Nama asosiasi yang bisa digunakan saat melakukan query
|
||||
});
|
||||
|
||||
// Asosiasi dengan model Penyakit
|
||||
Rule.belongsTo(models.Penyakit, {
|
||||
Rule_penyakit.belongsTo(models.Penyakit, {
|
||||
foreignKey: 'id_penyakit',
|
||||
as: 'penyakit',
|
||||
});
|
||||
|
||||
// Asosiasi dengan model Hama
|
||||
Rule.belongsTo(models.Hama, {
|
||||
foreignKey: 'id_hama',
|
||||
as: 'hama',
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
Rule.init(
|
||||
Rule_penyakit.init(
|
||||
{
|
||||
id_gejala: {
|
||||
type: DataTypes.INTEGER,
|
||||
|
@ -47,24 +42,16 @@ Rule.init(
|
|||
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,
|
||||
modelName: 'Rule',
|
||||
tableName: 'rules',
|
||||
modelName: 'Rule_penyakit',
|
||||
tableName: 'rules_penyakit',
|
||||
timestamps: false,
|
||||
paranoid: false,
|
||||
}
|
||||
);
|
||||
|
||||
return Rule;
|
||||
return Rule_penyakit;
|
||||
|
||||
}
|
|
@ -1,5 +1,5 @@
|
|||
const { Model, DataTypes } = require('sequelize');
|
||||
|
||||
const sequelize = require('../config/database');
|
||||
|
||||
module.exports = (sequelize) => {
|
||||
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
|
||||
* tags:
|
||||
* name: Rules
|
||||
* name: Rules_penyakit
|
||||
* description: API untuk mengelola aturan (rules)
|
||||
*/
|
||||
|
||||
/**
|
||||
* @swagger
|
||||
* /api/rules:
|
||||
* /api/rules_penyakit:
|
||||
* post:
|
||||
* summary: Membuat aturan baru
|
||||
* tags: [Rules]
|
||||
* tags: [Rules_penyakit]
|
||||
* requestBody:
|
||||
* required: true
|
||||
* content:
|
||||
|
@ -29,8 +29,6 @@ const ruleController = require('../controller/rulesController');
|
|||
* type: integer
|
||||
* id_penyakit:
|
||||
* type: integer
|
||||
* id_hama:
|
||||
* type: integer
|
||||
* nilai_pakar:
|
||||
* type: number
|
||||
* format: float
|
||||
|
@ -42,28 +40,28 @@ const ruleController = require('../controller/rulesController');
|
|||
* 500:
|
||||
* description: Terjadi kesalahan server
|
||||
*/
|
||||
router.post('/', ruleController.createRule);
|
||||
router.post('/', ruleController.createRulePenyakit);
|
||||
|
||||
/**
|
||||
* @swagger
|
||||
* /api/rules:
|
||||
* /api/rules_penyakit:
|
||||
* get:
|
||||
* summary: Menampilkan semua aturan
|
||||
* tags: [Rules]
|
||||
* tags: [Rules_penyakit]
|
||||
* responses:
|
||||
* 200:
|
||||
* description: Daftar rules berhasil diambil
|
||||
* 500:
|
||||
* description: Terjadi kesalahan server
|
||||
*/
|
||||
router.get('/', ruleController.getRules);
|
||||
router.get('/', ruleController.getRulesPenyakit);
|
||||
|
||||
/**
|
||||
* @swagger
|
||||
* /api/rules/{id}:
|
||||
* /api/rules_penyakit/{id}:
|
||||
* put:
|
||||
* summary: Memperbarui aturan berdasarkan ID
|
||||
* tags: [Rules]
|
||||
* tags: [Rules_penyakit]
|
||||
* parameters:
|
||||
* - in: path
|
||||
* name: id
|
||||
|
@ -82,8 +80,6 @@ router.get('/', ruleController.getRules);
|
|||
* type: integer
|
||||
* id_penyakit:
|
||||
* type: integer
|
||||
* id_hama:
|
||||
* type: integer
|
||||
* nilai_pakar:
|
||||
* type: number
|
||||
* format: float
|
||||
|
@ -95,14 +91,14 @@ router.get('/', ruleController.getRules);
|
|||
* 500:
|
||||
* description: Terjadi kesalahan server
|
||||
*/
|
||||
router.put('/:id', ruleController.updateRule);
|
||||
router.put('/:id', ruleController.updateRulePenyakit);
|
||||
|
||||
/**
|
||||
* @swagger
|
||||
* /api/rules/{id}:
|
||||
* /api/rules_penyakit/{id}:
|
||||
* delete:
|
||||
* summary: Menghapus aturan berdasarkan ID
|
||||
* tags: [Rules]
|
||||
* tags: [Rules_penyakit]
|
||||
* parameters:
|
||||
* - in: path
|
||||
* name: id
|
||||
|
@ -118,6 +114,6 @@ router.put('/:id', ruleController.updateRule);
|
|||
* 500:
|
||||
* description: Terjadi kesalahan server
|
||||
*/
|
||||
router.delete('/:id', ruleController.deleteRule);
|
||||
router.delete('/:id', ruleController.deleteRulePenyakit);
|
||||
|
||||
module.exports = router;
|
||||
|
|
|
@ -2,6 +2,7 @@ import 'package:flutter/material.dart';
|
|||
import 'hama_page.dart';
|
||||
import 'penyakit_page.dart';
|
||||
import 'gejala_page.dart';
|
||||
import 'rule_page.dart';
|
||||
import 'package:frontend/api_services/api_services.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)),
|
||||
],
|
||||
),
|
||||
|
|
|
@ -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
|
||||
int currentPage = 0;
|
||||
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 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 rulesHamaUrl = 'http://localhost:5000/api/rules_hama';
|
||||
|
||||
// Fungsi Login (dengan perbaikan)
|
||||
static Future<Map<String, dynamic>> loginUser(String email, String password) async {
|
||||
// Fungsi Login (dengan perbaikan)
|
||||
static Future<Map<String, dynamic>> loginUser(
|
||||
String email,
|
||||
String password,
|
||||
) async {
|
||||
try {
|
||||
final response = await http.post(
|
||||
Uri.parse("$baseUrl/login"),
|
||||
|
@ -114,31 +120,38 @@ class ApiService {
|
|||
|
||||
// Ambil semua hama
|
||||
Future<List<Map<String, dynamic>>> getHama() async {
|
||||
try {
|
||||
final response = await http.get(Uri.parse(ApiService.hamaUrl));
|
||||
|
||||
if (response.statusCode == 200) {
|
||||
final responseData = jsonDecode(response.body);
|
||||
try {
|
||||
final response = await http.get(Uri.parse(ApiService.hamaUrl));
|
||||
|
||||
// Pastikan "data" ada dan berupa List
|
||||
if (responseData is Map<String, dynamic> && responseData.containsKey("data")) {
|
||||
final List<dynamic> data = responseData["data"];
|
||||
if (response.statusCode == 200) {
|
||||
final responseData = jsonDecode(response.body);
|
||||
|
||||
return List<Map<String, dynamic>>.from(data.map((item) => Map<String, dynamic>.from(item)));
|
||||
// Pastikan "data" ada dan berupa List
|
||||
if (responseData is Map<String, dynamic> &&
|
||||
responseData.containsKey("data")) {
|
||||
final List<dynamic> data = responseData["data"];
|
||||
|
||||
return List<Map<String, dynamic>>.from(
|
||||
data.map((item) => Map<String, dynamic>.from(item)),
|
||||
);
|
||||
} else {
|
||||
throw Exception("Format respons API tidak sesuai");
|
||||
}
|
||||
} 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");
|
||||
}
|
||||
} catch (e) {
|
||||
print("Error getHama: $e");
|
||||
throw Exception("Gagal mengambil data hama");
|
||||
}
|
||||
}
|
||||
|
||||
// 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 {
|
||||
final response = await http.post(
|
||||
Uri.parse(hamaUrl),
|
||||
|
@ -146,7 +159,7 @@ class ApiService {
|
|||
body: jsonEncode({
|
||||
"nama": nama,
|
||||
"deskripsi": deskripsi,
|
||||
"penanganan": penanganan
|
||||
"penanganan": penanganan,
|
||||
}),
|
||||
);
|
||||
|
||||
|
@ -161,15 +174,21 @@ class ApiService {
|
|||
}
|
||||
}
|
||||
|
||||
// Update hama berdasarkan ID
|
||||
Future<Map<String, dynamic>> updateHama(int id, String nama, String deskripsi, String penanganan) async {
|
||||
// Update hama berdasarkan ID
|
||||
Future<Map<String, dynamic>> updateHama(
|
||||
int id,
|
||||
String nama,
|
||||
String deskripsi,
|
||||
String penanganan,
|
||||
) async {
|
||||
try {
|
||||
final response = await http.put(Uri.parse('$hamaUrl/$id'),
|
||||
final response = await http.put(
|
||||
Uri.parse('$hamaUrl/$id'),
|
||||
headers: {"Content-Type": "application/json"},
|
||||
body: jsonEncode({
|
||||
"nama": nama,
|
||||
"deskripsi": deskripsi,
|
||||
"penanganan": penanganan
|
||||
"penanganan": penanganan,
|
||||
}),
|
||||
);
|
||||
|
||||
|
@ -199,39 +218,46 @@ class ApiService {
|
|||
|
||||
// Ambil semua penyakit
|
||||
Future<List<Map<String, dynamic>>> getPenyakit() async {
|
||||
try {
|
||||
final response = await http.get(Uri.parse(ApiService.penyakitUrl));
|
||||
|
||||
if (response.statusCode == 200) {
|
||||
final responseData = jsonDecode(response.body);
|
||||
try {
|
||||
final response = await http.get(Uri.parse(ApiService.penyakitUrl));
|
||||
|
||||
// Pastikan "data" ada dan berupa List
|
||||
if (responseData is Map<String, dynamic> && responseData.containsKey("data")) {
|
||||
final List<dynamic> data = responseData["data"];
|
||||
if (response.statusCode == 200) {
|
||||
final responseData = jsonDecode(response.body);
|
||||
|
||||
return List<Map<String, dynamic>>.from(data.map((item) => Map<String, dynamic>.from(item)));
|
||||
// Pastikan "data" ada dan berupa List
|
||||
if (responseData is Map<String, dynamic> &&
|
||||
responseData.containsKey("data")) {
|
||||
final List<dynamic> data = responseData["data"];
|
||||
|
||||
return List<Map<String, dynamic>>.from(
|
||||
data.map((item) => Map<String, dynamic>.from(item)),
|
||||
);
|
||||
} else {
|
||||
throw Exception("Format respons API tidak sesuai");
|
||||
}
|
||||
} 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");
|
||||
}
|
||||
} catch (e) {
|
||||
print("Error getHama: $e");
|
||||
throw Exception("Gagal mengambil data penyakit");
|
||||
}
|
||||
}
|
||||
|
||||
// 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 {
|
||||
final response = await http.post(
|
||||
Uri.parse(penyakitUrl),
|
||||
headers: {"Content-Type": "application/json"},
|
||||
body: jsonEncode({
|
||||
"nama": nama,
|
||||
"deskripsi": deskripsi,
|
||||
"penanganan": penanganan
|
||||
"deskripsi": deskripsi,
|
||||
"penanganan": penanganan,
|
||||
}),
|
||||
);
|
||||
|
||||
|
@ -246,15 +272,21 @@ class ApiService {
|
|||
}
|
||||
}
|
||||
|
||||
// Update penyakit berdasarkan ID
|
||||
Future<Map<String, dynamic>> updatePenyakit(int id, String nama, String deskripsi, String penanganan) async {
|
||||
// Update penyakit berdasarkan ID
|
||||
Future<Map<String, dynamic>> updatePenyakit(
|
||||
int id,
|
||||
String nama,
|
||||
String deskripsi,
|
||||
String penanganan,
|
||||
) async {
|
||||
try {
|
||||
final response = await http.put(Uri.parse('$penyakitUrl/$id'),
|
||||
final response = await http.put(
|
||||
Uri.parse('$penyakitUrl/$id'),
|
||||
headers: {"Content-Type": "application/json"},
|
||||
body: jsonEncode({
|
||||
"nama": nama,
|
||||
"deskripsi": deskripsi,
|
||||
"penanganan": penanganan
|
||||
"penanganan": penanganan,
|
||||
}),
|
||||
);
|
||||
|
||||
|
@ -282,7 +314,7 @@ class ApiService {
|
|||
}
|
||||
}
|
||||
|
||||
//registrasi
|
||||
//registrasi
|
||||
Future<void> registerUser({
|
||||
required String name,
|
||||
required String email,
|
||||
|
@ -304,7 +336,9 @@ class ApiService {
|
|||
);
|
||||
|
||||
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) {
|
||||
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