feat: fungsi rule
This commit is contained in:
parent
accd4ab167
commit
4271210c03
|
@ -8,6 +8,7 @@ const authRoutes = require('./routes/authRoutes');
|
||||||
const gejalaRoutes = require('./routes/gejalaRoute');
|
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 swaggerDocs = require('./swagger');
|
const swaggerDocs = require('./swagger');
|
||||||
|
|
||||||
dotenv.config();
|
dotenv.config();
|
||||||
|
@ -24,6 +25,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);
|
||||||
|
|
||||||
|
|
||||||
// Swagger Documentation
|
// Swagger Documentation
|
||||||
swaggerDocs(app); // Setup Swagger UI documentation
|
swaggerDocs(app); // Setup Swagger UI documentation
|
||||||
|
|
|
@ -0,0 +1,81 @@
|
||||||
|
const { Rule, gejala, penyakit, hama } = require('../models');
|
||||||
|
|
||||||
|
// 🔥 Buat aturan baru
|
||||||
|
exports.createRule = async (req, res) => {
|
||||||
|
try {
|
||||||
|
const { id_gejala, id_penyakit, id_hama, nilai_pakar } = req.body;
|
||||||
|
|
||||||
|
// Validasi minimal
|
||||||
|
if (!id_gejala || (!id_penyakit && !id_hama) || !nilai_pakar) {
|
||||||
|
return res.status(400).json({ message: 'Data tidak lengkap' });
|
||||||
|
}
|
||||||
|
|
||||||
|
const newRule = await Rule.create({
|
||||||
|
id_gejala,
|
||||||
|
id_penyakit,
|
||||||
|
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.getRules = async (req, res) => {
|
||||||
|
try {
|
||||||
|
const rules = await Rule.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.updateRule = async (req, res) => {
|
||||||
|
try {
|
||||||
|
const { id } = req.params;
|
||||||
|
const { id_gejala, id_penyakit, id_hama, nilai_pakar } = req.body;
|
||||||
|
|
||||||
|
const rule = await Rule.findByPk(id);
|
||||||
|
if (!rule) {
|
||||||
|
return res.status(404).json({ message: 'Rule tidak ditemukan' });
|
||||||
|
}
|
||||||
|
|
||||||
|
await rule.update({
|
||||||
|
id_gejala,
|
||||||
|
id_penyakit,
|
||||||
|
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.deleteRule = async (req, res) => {
|
||||||
|
try {
|
||||||
|
const { id } = req.params;
|
||||||
|
|
||||||
|
const rule = await Rule.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 });
|
||||||
|
}
|
||||||
|
};
|
|
@ -0,0 +1,42 @@
|
||||||
|
'use strict';
|
||||||
|
/** @type {import('sequelize-cli').Migration} */
|
||||||
|
module.exports = {
|
||||||
|
async up(queryInterface, Sequelize) {
|
||||||
|
await queryInterface.createTable('Rules', {
|
||||||
|
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,
|
||||||
|
allowNull: false
|
||||||
|
},
|
||||||
|
id_penyakit: {
|
||||||
|
type: Sequelize.INTEGER,
|
||||||
|
references:{
|
||||||
|
model: 'penyakit',
|
||||||
|
key:'id'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
id_hama: {
|
||||||
|
type: Sequelize.INTEGER,
|
||||||
|
references:{
|
||||||
|
model: 'hama',
|
||||||
|
key: 'id'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
});
|
||||||
|
},
|
||||||
|
async down(queryInterface, Sequelize) {
|
||||||
|
await queryInterface.dropTable('Rules');
|
||||||
|
}
|
||||||
|
};
|
|
@ -1,32 +1,33 @@
|
||||||
const { Model, DataTypes } = require('sequelize');
|
const { Model, DataTypes } = require('sequelize');
|
||||||
const sequelize = require('../config/database');
|
|
||||||
|
|
||||||
class Gejala extends Model {}
|
module.exports = (sequelize) => {
|
||||||
|
class Gejala extends Model {}
|
||||||
|
|
||||||
Gejala.init(
|
Gejala.init(
|
||||||
{
|
{
|
||||||
id: {
|
id: {
|
||||||
allowNull: false,
|
allowNull: false,
|
||||||
autoIncrement: true,
|
autoIncrement: true,
|
||||||
primaryKey: true,
|
primaryKey: true,
|
||||||
type: DataTypes.INTEGER,
|
type: DataTypes.INTEGER,
|
||||||
|
},
|
||||||
|
kode: {
|
||||||
|
type: DataTypes.STRING,
|
||||||
|
allowNull: false,
|
||||||
|
},
|
||||||
|
nama: {
|
||||||
|
type: DataTypes.STRING,
|
||||||
|
allowNull: false,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
kode: {
|
{
|
||||||
type: DataTypes.STRING,
|
sequelize,
|
||||||
allowNull: false,
|
modelName: 'Gejala',
|
||||||
},
|
tableName: 'gejala',
|
||||||
nama: {
|
timestamps: false, // Jika ingin menggunakan createdAt & updatedAt, ubah ke true
|
||||||
type: DataTypes.STRING,
|
paranoid: false, // Jika menggunakan soft delete, ubah ke true
|
||||||
allowNull: false,
|
}
|
||||||
},
|
);
|
||||||
},
|
|
||||||
{
|
|
||||||
sequelize,
|
|
||||||
modelName: 'Gejala',
|
|
||||||
tableName: 'gejala',
|
|
||||||
timestamps: false, // Jika ingin menggunakan createdAt & updatedAt, ubah ke true
|
|
||||||
paranoid: false, // Jika menggunakan soft delete, ubah ke true
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
module.exports = Gejala;
|
return Gejala; // Pastikan model dikembalikan dengan benar
|
||||||
|
};
|
||||||
|
|
|
@ -1,44 +1,45 @@
|
||||||
const { Model, DataTypes } = require('sequelize');
|
const { Model, DataTypes } = require('sequelize');
|
||||||
const sequelize = require('../config/database');
|
|
||||||
|
|
||||||
class Hama extends Model {}
|
|
||||||
|
|
||||||
Hama.init(
|
module.exports = (sequelize) => {
|
||||||
{
|
class Hama extends Model {}
|
||||||
id: {
|
|
||||||
allowNull: false,
|
Hama.init(
|
||||||
autoIncrement: true,
|
{
|
||||||
primaryKey: true,
|
id: {
|
||||||
type: DataTypes.INTEGER,
|
allowNull: false,
|
||||||
|
autoIncrement: true,
|
||||||
|
primaryKey: true,
|
||||||
|
type: DataTypes.INTEGER,
|
||||||
|
},
|
||||||
|
kode: {
|
||||||
|
type: DataTypes.STRING,
|
||||||
|
allowNull: false,
|
||||||
|
},
|
||||||
|
nama: {
|
||||||
|
type: DataTypes.STRING,
|
||||||
|
allowNull: false,
|
||||||
|
},
|
||||||
|
deskripsi: {
|
||||||
|
type: DataTypes.STRING,
|
||||||
|
allowNull: true,
|
||||||
|
},
|
||||||
|
penanganan: {
|
||||||
|
type: DataTypes.STRING,
|
||||||
|
allowNull: true,
|
||||||
|
},
|
||||||
|
foto: {
|
||||||
|
type: DataTypes.STRING,
|
||||||
|
allowNull: false,
|
||||||
|
}
|
||||||
},
|
},
|
||||||
kode: {
|
{
|
||||||
type: DataTypes.STRING,
|
sequelize,
|
||||||
allowNull: false,
|
modelName: 'Hama',
|
||||||
},
|
tableName: 'hama',
|
||||||
nama: {
|
timestamps: false, // Jika ingin menggunakan createdAt & updatedAt, ubah ke true
|
||||||
type: DataTypes.STRING,
|
paranoid: false, // Jika menggunakan soft delete, ubah ke true
|
||||||
allowNull: false,
|
|
||||||
},
|
|
||||||
deskripsi: {
|
|
||||||
type: DataTypes.STRING,
|
|
||||||
allowNull: true,
|
|
||||||
},
|
|
||||||
penanganan: {
|
|
||||||
type: DataTypes.STRING,
|
|
||||||
allowNull: true,
|
|
||||||
},
|
|
||||||
foto: {
|
|
||||||
type: DataTypes.STRING,
|
|
||||||
allowNull: false,
|
|
||||||
}
|
}
|
||||||
},
|
);
|
||||||
{
|
return Hama;
|
||||||
sequelize,
|
}
|
||||||
modelName: 'Hama',
|
|
||||||
tableName: 'hama',
|
|
||||||
timestamps: false, // Jika ingin menggunakan createdAt & updatedAt, ubah ke true
|
|
||||||
paranoid: false, // Jika menggunakan soft delete, ubah ke true
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
module.exports = Hama;
|
|
|
@ -1,40 +1,42 @@
|
||||||
const { Model, DataTypes } = require('sequelize');
|
const { Model, DataTypes } = require('sequelize');
|
||||||
const sequelize = require('../config/database');
|
|
||||||
|
|
||||||
class Penyakit extends Model {}
|
|
||||||
|
|
||||||
Penyakit.init(
|
module.exports =(sequelize) => {
|
||||||
{
|
class Penyakit extends Model {}
|
||||||
id: {
|
|
||||||
allowNull: false,
|
|
||||||
autoIncrement: true,
|
|
||||||
primaryKey: true,
|
|
||||||
type: DataTypes.INTEGER,
|
|
||||||
},
|
|
||||||
kode: {
|
|
||||||
type: DataTypes.STRING,
|
|
||||||
allowNull: false,
|
|
||||||
},
|
|
||||||
nama: {
|
|
||||||
type: DataTypes.STRING,
|
|
||||||
allowNull: false,
|
|
||||||
},
|
|
||||||
deskripsi: {
|
|
||||||
type: DataTypes.STRING,
|
|
||||||
allowNull: true,
|
|
||||||
},
|
|
||||||
penanganan: {
|
|
||||||
type: DataTypes.STRING,
|
|
||||||
allowNull: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
sequelize,
|
|
||||||
modelName: 'Penyakit',
|
|
||||||
tableName: 'penyakit',
|
|
||||||
timestamps: false, // Jika ingin menggunakan createdAt & updatedAt, ubah ke true
|
|
||||||
paranoid: false, // Jika menggunakan soft delete, ubah ke true
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
module.exports = Penyakit;
|
Penyakit.init(
|
||||||
|
{
|
||||||
|
id: {
|
||||||
|
allowNull: false,
|
||||||
|
autoIncrement: true,
|
||||||
|
primaryKey: true,
|
||||||
|
type: DataTypes.INTEGER,
|
||||||
|
},
|
||||||
|
kode: {
|
||||||
|
type: DataTypes.STRING,
|
||||||
|
allowNull: false,
|
||||||
|
},
|
||||||
|
nama: {
|
||||||
|
type: DataTypes.STRING,
|
||||||
|
allowNull: false,
|
||||||
|
},
|
||||||
|
deskripsi: {
|
||||||
|
type: DataTypes.STRING,
|
||||||
|
allowNull: true,
|
||||||
|
},
|
||||||
|
penanganan: {
|
||||||
|
type: DataTypes.STRING,
|
||||||
|
allowNull: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
sequelize,
|
||||||
|
modelName: 'Penyakit',
|
||||||
|
tableName: 'penyakit',
|
||||||
|
timestamps: false, // Jika ingin menggunakan createdAt & updatedAt, ubah ke true
|
||||||
|
paranoid: false, // Jika menggunakan soft delete, ubah ke true
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
return Penyakit;
|
||||||
|
}
|
|
@ -0,0 +1,70 @@
|
||||||
|
const { Model, DataTypes } = require('sequelize');
|
||||||
|
|
||||||
|
|
||||||
|
module.exports = (sequelize) => {
|
||||||
|
|
||||||
|
class Rule extends Model {
|
||||||
|
static associate(models) {
|
||||||
|
// Asosiasi dengan model Gejala
|
||||||
|
Rule.belongsTo(models.Gejala, {
|
||||||
|
foreignKey: 'id_gejala',
|
||||||
|
as: 'gejala', // Nama asosiasi yang bisa digunakan saat melakukan query
|
||||||
|
});
|
||||||
|
|
||||||
|
// Asosiasi dengan model Penyakit
|
||||||
|
Rule.belongsTo(models.Penyakit, {
|
||||||
|
foreignKey: 'id_penyakit',
|
||||||
|
as: 'penyakit',
|
||||||
|
});
|
||||||
|
|
||||||
|
// Asosiasi dengan model Hama
|
||||||
|
Rule.belongsTo(models.Hama, {
|
||||||
|
foreignKey: 'id_hama',
|
||||||
|
as: 'hama',
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Rule.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_penyakit: {
|
||||||
|
type: DataTypes.INTEGER,
|
||||||
|
allowNull: true,
|
||||||
|
references: {
|
||||||
|
model: 'penyakit', // Mengacu ke 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,
|
||||||
|
modelName: 'Rule',
|
||||||
|
tableName: 'rules',
|
||||||
|
timestamps: false,
|
||||||
|
paranoid: false,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
return Rule;
|
||||||
|
|
||||||
|
}
|
|
@ -1,53 +1,54 @@
|
||||||
const { Model, DataTypes } = require('sequelize');
|
const { Model, DataTypes } = require('sequelize');
|
||||||
const sequelize = require('../config/database');
|
|
||||||
|
|
||||||
class User extends Model {}
|
|
||||||
|
|
||||||
User.init(
|
module.exports = (sequelize) => {
|
||||||
{
|
class User extends Model {}
|
||||||
id: {
|
|
||||||
allowNull: false,
|
User.init(
|
||||||
autoIncrement: true,
|
{
|
||||||
primaryKey: true,
|
id: {
|
||||||
type: DataTypes.INTEGER,
|
allowNull: false,
|
||||||
},
|
autoIncrement: true,
|
||||||
name: {
|
primaryKey: true,
|
||||||
type: DataTypes.STRING,
|
type: DataTypes.INTEGER,
|
||||||
allowNull: true,
|
},
|
||||||
},
|
name: {
|
||||||
email: {
|
type: DataTypes.STRING,
|
||||||
type: DataTypes.STRING,
|
allowNull: true,
|
||||||
allowNull: false,
|
},
|
||||||
unique: true,
|
email: {
|
||||||
validate: {
|
type: DataTypes.STRING,
|
||||||
isEmail: true,
|
allowNull: false,
|
||||||
|
unique: true,
|
||||||
|
validate: {
|
||||||
|
isEmail: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
password: {
|
||||||
|
type: DataTypes.STRING,
|
||||||
|
allowNull: false,
|
||||||
|
},
|
||||||
|
alamat: {
|
||||||
|
type: DataTypes.STRING,
|
||||||
|
allowNull: true,
|
||||||
|
},
|
||||||
|
nomorTelepon: {
|
||||||
|
type: DataTypes.STRING,
|
||||||
|
allowNull: true,
|
||||||
|
},
|
||||||
|
role: {
|
||||||
|
type: DataTypes.STRING,
|
||||||
|
allowNull: false,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
{
|
||||||
password: {
|
sequelize,
|
||||||
type: DataTypes.STRING,
|
modelName: 'User',
|
||||||
allowNull: false,
|
tableName: 'users',
|
||||||
},
|
timestamps: false, // Pastikan timestamps aktif jika menggunakan paranoid
|
||||||
alamat: {
|
paranoid: false, // Hanya gunakan ini jika timestamps: true
|
||||||
type: DataTypes.STRING,
|
|
||||||
allowNull: true,
|
}
|
||||||
},
|
);
|
||||||
nomorTelepon: {
|
return User;
|
||||||
type: DataTypes.STRING,
|
}
|
||||||
allowNull: true,
|
|
||||||
},
|
|
||||||
role: {
|
|
||||||
type: DataTypes.STRING,
|
|
||||||
allowNull: false,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
sequelize,
|
|
||||||
modelName: 'User',
|
|
||||||
tableName: 'users',
|
|
||||||
timestamps: false, // Pastikan timestamps aktif jika menggunakan paranoid
|
|
||||||
paranoid: false, // Hanya gunakan ini jika timestamps: true
|
|
||||||
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
module.exports = User;
|
|
||||||
|
|
|
@ -0,0 +1,123 @@
|
||||||
|
const express = require('express');
|
||||||
|
const router = express.Router();
|
||||||
|
const ruleController = require('../controller/rulesController');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @swagger
|
||||||
|
* tags:
|
||||||
|
* name: Rules
|
||||||
|
* description: API untuk mengelola aturan (rules)
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @swagger
|
||||||
|
* /api/rules:
|
||||||
|
* post:
|
||||||
|
* summary: Membuat aturan baru
|
||||||
|
* tags: [Rules]
|
||||||
|
* requestBody:
|
||||||
|
* required: true
|
||||||
|
* content:
|
||||||
|
* application/json:
|
||||||
|
* schema:
|
||||||
|
* type: object
|
||||||
|
* required:
|
||||||
|
* - id_gejala
|
||||||
|
* - nilai_pakar
|
||||||
|
* properties:
|
||||||
|
* id_gejala:
|
||||||
|
* type: integer
|
||||||
|
* id_penyakit:
|
||||||
|
* 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.createRule);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @swagger
|
||||||
|
* /api/rules:
|
||||||
|
* get:
|
||||||
|
* summary: Menampilkan semua aturan
|
||||||
|
* tags: [Rules]
|
||||||
|
* responses:
|
||||||
|
* 200:
|
||||||
|
* description: Daftar rules berhasil diambil
|
||||||
|
* 500:
|
||||||
|
* description: Terjadi kesalahan server
|
||||||
|
*/
|
||||||
|
router.get('/', ruleController.getRules);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @swagger
|
||||||
|
* /api/rules/{id}:
|
||||||
|
* put:
|
||||||
|
* summary: Memperbarui aturan berdasarkan ID
|
||||||
|
* tags: [Rules]
|
||||||
|
* 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_penyakit:
|
||||||
|
* 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.updateRule);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @swagger
|
||||||
|
* /api/rules/{id}:
|
||||||
|
* delete:
|
||||||
|
* summary: Menghapus aturan berdasarkan ID
|
||||||
|
* tags: [Rules]
|
||||||
|
* 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.deleteRule);
|
||||||
|
|
||||||
|
module.exports = router;
|
|
@ -1,9 +1,9 @@
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
class DetailHamaPage extends StatelessWidget {
|
class DetailHamaPage extends StatelessWidget {
|
||||||
final Map<String, String> detailRiwayat;
|
final Map<String, dynamic> detailHama;
|
||||||
|
|
||||||
const DetailHamaPage({required this.detailRiwayat});
|
const DetailHamaPage({required this.detailHama});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
|
@ -25,11 +25,11 @@ class DetailHamaPage extends StatelessWidget {
|
||||||
padding: const EdgeInsets.all(16.0),
|
padding: const EdgeInsets.all(16.0),
|
||||||
child: Column(
|
child: Column(
|
||||||
children: [
|
children: [
|
||||||
if (detailRiwayat["gambar"] != null && detailRiwayat["gambar"]!.isNotEmpty)
|
if (detailHama["gambar"] != null && detailHama["gambar"]!.isNotEmpty)
|
||||||
ClipRRect(
|
ClipRRect(
|
||||||
borderRadius: BorderRadius.circular(12),
|
borderRadius: BorderRadius.circular(12),
|
||||||
child: Image.asset(
|
child: Image.asset(
|
||||||
detailRiwayat["gambar"]!,
|
detailHama["gambar"]!,
|
||||||
height: 200,
|
height: 200,
|
||||||
width: 200, // Biar gambar full lebar
|
width: 200, // Biar gambar full lebar
|
||||||
fit: BoxFit.cover,
|
fit: BoxFit.cover,
|
||||||
|
@ -54,7 +54,7 @@ class DetailHamaPage extends StatelessWidget {
|
||||||
),
|
),
|
||||||
SizedBox(height: 8),
|
SizedBox(height: 8),
|
||||||
Text(
|
Text(
|
||||||
detailRiwayat["nama hama"] ?? "Nama hama tidak tersedia",
|
detailHama["nama"] ?? "Nama hama tidak tersedia",
|
||||||
style: TextStyle(fontSize: 16),
|
style: TextStyle(fontSize: 16),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
@ -81,7 +81,7 @@ class DetailHamaPage extends StatelessWidget {
|
||||||
),
|
),
|
||||||
SizedBox(height: 8),
|
SizedBox(height: 8),
|
||||||
Text(
|
Text(
|
||||||
detailRiwayat["deskripsi"] ?? "Deskripsi tidak tersedia",
|
detailHama["deskripsi"] ?? "Deskripsi tidak tersedia",
|
||||||
style: TextStyle(fontSize: 16),
|
style: TextStyle(fontSize: 16),
|
||||||
),
|
),
|
||||||
SizedBox(height: 16),
|
SizedBox(height: 16),
|
||||||
|
@ -91,7 +91,7 @@ class DetailHamaPage extends StatelessWidget {
|
||||||
),
|
),
|
||||||
SizedBox(height: 8),
|
SizedBox(height: 8),
|
||||||
Text(
|
Text(
|
||||||
detailRiwayat["penanganan"] ?? "Penanganan tidak tersedia",
|
detailHama["penanganan"] ?? "Penanganan tidak tersedia",
|
||||||
style: TextStyle(fontSize: 16),
|
style: TextStyle(fontSize: 16),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
class DetailPenyakitPage extends StatelessWidget {
|
class DetailPenyakitPage extends StatelessWidget {
|
||||||
final Map<String, String> detailPenyakit;
|
final Map<String, dynamic> detailPenyakit;
|
||||||
|
|
||||||
const DetailPenyakitPage({required this.detailPenyakit});
|
const DetailPenyakitPage({required this.detailPenyakit});
|
||||||
|
|
||||||
|
@ -54,7 +54,7 @@ class DetailPenyakitPage extends StatelessWidget {
|
||||||
),
|
),
|
||||||
SizedBox(height: 8),
|
SizedBox(height: 8),
|
||||||
Text(
|
Text(
|
||||||
detailPenyakit["nama penyakit"] ?? "Nama penyakit tidak tersedia",
|
detailPenyakit["nama"] ?? "Nama penyakit tidak tersedia",
|
||||||
style: TextStyle(fontSize: 16),
|
style: TextStyle(fontSize: 16),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
|
|
@ -1,33 +1,20 @@
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'detail_hama_page.dart';
|
import 'detail_hama_page.dart';
|
||||||
|
import 'package:frontend/api_services/api_services.dart';
|
||||||
|
|
||||||
class HamaPage extends StatelessWidget {
|
class HamaPage extends StatefulWidget {
|
||||||
final List<Map<String, String>> hamaList = [
|
@override
|
||||||
{
|
_HamaPageState createState() => _HamaPageState();
|
||||||
"nama hama": "Karat Putih",
|
}
|
||||||
"deskripsi": "Penyakit yang umum pada bayam.",
|
|
||||||
"penanganan": "Gunakan fungisida sesuai anjuran dan potong daun yang terinfeksi.",
|
class _HamaPageState extends State<HamaPage> {
|
||||||
"gambar": "assets/images/karat putih.jpeg",
|
late Future<List<Map<String, dynamic>>> _hamaListFuture;
|
||||||
},
|
|
||||||
{
|
@override
|
||||||
"nama hama": "Virus Keriting",
|
void initState() {
|
||||||
"deskripsi": "Disebabkan oleh infeksi virus.",
|
super.initState();
|
||||||
"penanganan": "Musnahkan tanaman terinfeksi dan kontrol vektor seperti kutu daun.",
|
_hamaListFuture = ApiService().getHama();
|
||||||
"gambar": "assets/images/virus_keriting.jpeg",
|
}
|
||||||
},
|
|
||||||
{
|
|
||||||
"nama hama": "Kekurangan Mangan",
|
|
||||||
"deskripsi": "Kekurangan unsur hara mikro.",
|
|
||||||
"penanganan": "Tambahkan pupuk yang mengandung mangan (Mn).",
|
|
||||||
"gambar": "assets/images/kekurangan_mangan.jpeg",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"nama hama": "Downy Mildew",
|
|
||||||
"deskripsi": "Penyakit jamur pada bayam.",
|
|
||||||
"penanganan": "Gunakan fungisida berbahan aktif metalaxyl dan perbaiki drainase tanah.",
|
|
||||||
"gambar": "assets/images/downy_mildew.jpeg",
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
|
@ -52,11 +39,19 @@ class HamaPage extends StatelessWidget {
|
||||||
),
|
),
|
||||||
body: Padding(
|
body: Padding(
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 16.0),
|
padding: const EdgeInsets.symmetric(horizontal: 16.0),
|
||||||
child: Column(
|
child: FutureBuilder<List<Map<String, dynamic>>>(
|
||||||
children: [
|
future: _hamaListFuture,
|
||||||
SizedBox(height: 16),
|
builder: (context, snapshot) {
|
||||||
Expanded(
|
if (snapshot.connectionState == ConnectionState.waiting) {
|
||||||
child: ListView.builder(
|
return Center(child: CircularProgressIndicator(color: Colors.white));
|
||||||
|
} else if (snapshot.hasError) {
|
||||||
|
return Center(child: Text('Gagal memuat data', style: TextStyle(color: Colors.white)));
|
||||||
|
} else if (!snapshot.hasData || snapshot.data!.isEmpty) {
|
||||||
|
return Center(child: Text('Tidak ada data tersedia', style: TextStyle(color: Colors.white)));
|
||||||
|
} else {
|
||||||
|
final hamaList = snapshot.data!;
|
||||||
|
|
||||||
|
return ListView.builder(
|
||||||
itemCount: hamaList.length,
|
itemCount: hamaList.length,
|
||||||
itemBuilder: (context, index) {
|
itemBuilder: (context, index) {
|
||||||
final diagnosa = hamaList[index];
|
final diagnosa = hamaList[index];
|
||||||
|
@ -65,7 +60,7 @@ class HamaPage extends StatelessWidget {
|
||||||
margin: const EdgeInsets.symmetric(vertical: 8),
|
margin: const EdgeInsets.symmetric(vertical: 8),
|
||||||
child: ListTile(
|
child: ListTile(
|
||||||
title: Text(
|
title: Text(
|
||||||
diagnosa["nama hama"] ?? "Tidak ada data",
|
diagnosa["nama"] ?? "Tidak ada data",
|
||||||
style: TextStyle(fontWeight: FontWeight.bold),
|
style: TextStyle(fontWeight: FontWeight.bold),
|
||||||
),
|
),
|
||||||
subtitle: Text(diagnosa["deskripsi"] ?? "Deskripsi tidak tersedia"),
|
subtitle: Text(diagnosa["deskripsi"] ?? "Deskripsi tidak tersedia"),
|
||||||
|
@ -73,18 +68,18 @@ class HamaPage extends StatelessWidget {
|
||||||
Navigator.push(
|
Navigator.push(
|
||||||
context,
|
context,
|
||||||
MaterialPageRoute(
|
MaterialPageRoute(
|
||||||
builder: (context) => DetailHamaPage(detailRiwayat: diagnosa),
|
builder: (context) => DetailHamaPage(detailHama: diagnosa),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
),
|
);
|
||||||
),
|
}
|
||||||
],
|
},
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,33 +1,20 @@
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'detail_penyakit_page.dart';
|
import 'detail_penyakit_page.dart';
|
||||||
|
import 'package:frontend/api_services/api_services.dart';
|
||||||
|
|
||||||
class PenyakitPage extends StatelessWidget {
|
class PenyakitPage extends StatefulWidget {
|
||||||
final List<Map<String, String>> penyakitList= [
|
@override
|
||||||
{
|
_PenyakitPageState createState() => _PenyakitPageState();
|
||||||
"nama penyakit": "Karat Putih",
|
}
|
||||||
"deskripsi": "Penyakit yang umum pada bayam.",
|
|
||||||
"penanganan": "Gunakan fungisida sesuai anjuran dan potong daun yang terinfeksi.",
|
class _PenyakitPageState extends State<PenyakitPage> {
|
||||||
"gambar": "assets/images/karat putih.jpeg",
|
late Future<List<Map<String, dynamic>>> _penyakitListFuture;
|
||||||
},
|
|
||||||
{
|
@override
|
||||||
"nama penyakit": "Virus Keriting",
|
void initState() {
|
||||||
"deskripsi": "Disebabkan oleh infeksi virus.",
|
super.initState();
|
||||||
"penanganan": "Musnahkan tanaman terinfeksi dan kontrol vektor seperti kutu daun.",
|
_penyakitListFuture = ApiService().getPenyakit();
|
||||||
"gambar": "assets/images/virus_keriting.jpeg",
|
}
|
||||||
},
|
|
||||||
{
|
|
||||||
"nama penyakit": "Kekurangan Mangan",
|
|
||||||
"deskripsi": "Kekurangan unsur hara mikro.",
|
|
||||||
"penanganan": "Tambahkan pupuk yang mengandung mangan (Mn).",
|
|
||||||
"gambar": "assets/images/kekurangan_mangan.jpeg",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"nama penyakit": "Downy Mildew",
|
|
||||||
"deskripsi": "Penyakit jamur pada bayam.",
|
|
||||||
"penanganan": "Gunakan fungisida berbahan aktif metalaxyl dan perbaiki drainase tanah.",
|
|
||||||
"gambar": "assets/images/downy_mildew.jpeg",
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
|
@ -52,39 +39,47 @@ class PenyakitPage extends StatelessWidget {
|
||||||
),
|
),
|
||||||
body: Padding(
|
body: Padding(
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 16.0),
|
padding: const EdgeInsets.symmetric(horizontal: 16.0),
|
||||||
child: Column(
|
child: FutureBuilder<List<Map<String, dynamic>>>(
|
||||||
children: [
|
future: _penyakitListFuture,
|
||||||
SizedBox(height: 16),
|
builder: (context, snapshot) {
|
||||||
Expanded(
|
if (snapshot.connectionState == ConnectionState.waiting) {
|
||||||
child: ListView.builder(
|
return Center(child: CircularProgressIndicator(color: Colors.white));
|
||||||
|
} else if (snapshot.hasError) {
|
||||||
|
return Center(child: Text('Gagal memuat data', style: TextStyle(color: Colors.white)));
|
||||||
|
} else if (!snapshot.hasData || snapshot.data!.isEmpty) {
|
||||||
|
return Center(child: Text('Tidak ada data tersedia', style: TextStyle(color: Colors.white)));
|
||||||
|
} else {
|
||||||
|
final penyakitList = snapshot.data!;
|
||||||
|
|
||||||
|
return ListView.builder(
|
||||||
itemCount: penyakitList.length,
|
itemCount: penyakitList.length,
|
||||||
itemBuilder: (context, index) {
|
itemBuilder: (context, index) {
|
||||||
final diagnosa = penyakitList[index];
|
final penyakit = penyakitList[index];
|
||||||
return Card(
|
return Card(
|
||||||
elevation: 4,
|
elevation: 4,
|
||||||
margin: const EdgeInsets.symmetric(vertical: 8),
|
margin: const EdgeInsets.symmetric(vertical: 8),
|
||||||
child: ListTile(
|
child: ListTile(
|
||||||
title: Text(
|
title: Text(
|
||||||
diagnosa["nama penyakit"] ?? "Tidak ada data",
|
penyakit["nama"] ?? "Tidak ada data",
|
||||||
style: TextStyle(fontWeight: FontWeight.bold),
|
style: TextStyle(fontWeight: FontWeight.bold),
|
||||||
),
|
),
|
||||||
subtitle: Text(diagnosa["deskripsi"] ?? "Deskripsi tidak tersedia"),
|
subtitle: Text(penyakit["deskripsi"] ?? "Deskripsi tidak tersedia"),
|
||||||
onTap: () {
|
onTap: () {
|
||||||
Navigator.push(
|
Navigator.push(
|
||||||
context,
|
context,
|
||||||
MaterialPageRoute(
|
MaterialPageRoute(
|
||||||
builder: (context) => DetailPenyakitPage(detailPenyakit: diagnosa),
|
builder: (context) => DetailPenyakitPage(detailPenyakit: penyakit),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
),
|
);
|
||||||
),
|
}
|
||||||
],
|
},
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue