Merge pull request #7 from arieeefajar/assessment-form

Assessment form
This commit is contained in:
Arie Fajar Bachtiar 2025-02-06 14:10:26 +07:00 committed by GitHub
commit aeaa40ab86
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
55 changed files with 516 additions and 72 deletions

View File

@ -0,0 +1,138 @@
<?php
namespace App\Http\Controllers;
use App\Models\EvaluationDetail;
use App\Models\Evalutaion;
use App\Models\Land;
use App\Models\Rule;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
class AssesmentFormController extends Controller
{
public function index()
{
$lands = Land::select('id', 'name')->orderBy('created_at', 'desc')->get();
return view('assesment-form.index', compact('lands'));
}
public function store(Request $request)
{
// Ambil semua nilai input
$parameters = [
1 => $request->input('1'), // pH
2 => $request->input('2'), // Ketinggian Tempat
3 => $request->input('3'), // Ketersediaan Air
4 => $request->input('4') // Curah Hujan
];
// Ambil rule untuk setiap parameter
$rules = Rule::whereIn('indicator_id', array_keys($parameters))->get()->keyBy('indicator_id');
// Hitung Certainty Factor (CF) untuk setiap parameter
$cfValues = [];
foreach ($parameters as $indicatorId => $value) {
if (isset($rules[$indicatorId])) {
$cfValues[$indicatorId] = $rules[$indicatorId]->mb - $rules[$indicatorId]->md;
} else {
toast("Rule untuk indikator ID {$indicatorId} tidak ditemukan.", 'error')->position('top')->autoclose(3000);
return redirect()->back();
}
}
// Simpan ke database dalam satu transaksi
DB::beginTransaction();
try {
// Simpan data evaluasi utama
$evaluation = new Evalutaion;
$evaluation->land_id = $request->land;
$evaluation->save();
// Simpan semua detail evaluasi
foreach ($parameters as $indicatorId => $value) {
EvaluationDetail::create([
'evaluation_id' => $evaluation->id,
'indicator_id' => $indicatorId,
'value' => $value,
'cf' => $cfValues[$indicatorId] ?? 0
]);
}
$result = "OKOKO";
DB::commit();
toast('Evaluasi berhasil disimpan!', 'success')->position('top')->autoclose(3000);
return redirect()->back()->with("result", $result);
} catch (\Throwable $th) {
DB::rollBack();
toast($th->getMessage(), 'error')->position('top')->autoclose(3000);
return redirect()->back();
}
}
// public function store(Request $request)
// {
// // dd($request->all());
// $pH = $request->input('1');
// $ketinggianTempat = $request->input('2');
// $ketersediaanAir = $request->input('3');
// $curahHujan = $request->input('4');
// $rulepH = Rule::where('indicator_id', 1)->where('range_min', '<=', $pH)->where('range_max', '>=', $pH)->first();
// $ruleKetinggianTempat = Rule::where('indicator_id', 2)->where('range_min', '<=', $ketinggianTempat)->where('range_max', '>=', $ketinggianTempat)->first();
// $ruleKetersediaanAir = Rule::where('indicator_id', 3)->where('range_min', '<=', $ketersediaanAir)->where('range_max', '>=', $ketersediaanAir)->first();
// $ruleCurahHujan = Rule::where('indicator_id', 4)->where('range_min', '<=', $curahHujan)->where('range_max', '>=', $curahHujan)->first();
// // dd([
// // "pH" => $pH,
// // "ketinggian_tempat" => $ketinggianTempat,
// // "ketersediaan_air" => $ketersediaanAir,
// // "curah_hujan" => $curahHujan,
// // ], [
// // "rulepH" => $rulepH,
// // "ruleKetinggianTempat" => $ruleKetinggianTempat,
// // "ruleKetersediaanAir" => $ruleKetersediaanAir,
// // "ruleCurahHujan" => $ruleCurahHujan
// // ]);
// $cfpH = $rulepH->mb - $rulepH->md;
// $cfketinggianTempat = $ruleKetinggianTempat->mb - $ruleKetinggianTempat->md;
// $cfketersediaanAir = $ruleKetersediaanAir->mb - $ruleKetersediaanAir->md;
// $cfcurahHujan = $ruleCurahHujan->mb - $ruleCurahHujan->md;
// // dd([
// // "pH" => $pH,
// // "ketinggian_tempat" => $ketinggianTempat,
// // "ketersediaan_air" => $ketersediaanAir,
// // "curah_hujan" => $curahHujan,
// // ], [
// // "rulepH" => $rulepH,
// // "ruleKetinggianTempat" => $ruleKetinggianTempat,
// // "ruleKetersediaanAir" => $ruleKetersediaanAir,
// // "ruleCurahHujan" => $ruleCurahHujan
// // ], [
// // "pH" => $cfpH,
// // "ketinggian_tempat" => $cfketinggianTempat,
// // "ketersediaan_air" => $cfketersediaanAir,
// // "curah_hujan" => $cfcurahHujan
// // ]);
// // $cfCombine1 = $cfpH + ($cfketinggianTempat * (1 - $cfpH));
// // $cfCombine2 = $cfCombine1 + ($cfketersediaanAir * (1 - $cfCombine1));
// // $cfCombine3 = $cfCombine2 + ($cfcurahHujan * (1 - $cfCombine2));
// // dd([
// // "cfCombine(cfpH,cfketinggian)" => $cfCombine1,
// // "cfCombine(cfOld, cfketersediaanAir)" => $cfCombine2,
// // "cfCombine(cfOld, cfCurahHujan)" => $cfCombine3,
// // ]);
// // $presentaseKeyakinan = $cfCombine3 * 100;
// // dd($presentaseKeyakinan);
// // return view('assesment-form.index')->with('result', $presentaseKeyakinan);
// }
}

View File

@ -64,5 +64,7 @@ class Kernel extends HttpKernel
'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class, 'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class,
'verified' => \Illuminate\Auth\Middleware\EnsureEmailIsVerified::class, 'verified' => \Illuminate\Auth\Middleware\EnsureEmailIsVerified::class,
'verifiedAcount' => \App\Http\Middleware\verifiedAcount::class, 'verifiedAcount' => \App\Http\Middleware\verifiedAcount::class,
'admin' => \App\Http\Middleware\AdminMiddleware::class,
'officer' => \App\Http\Middleware\OfficerMiddleware::class
]; ];
} }

View File

@ -0,0 +1,26 @@
<?php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Symfony\Component\HttpFoundation\Response;
class AdminMiddleware
{
/**
* Handle an incoming request.
*
* @param \Closure(\Illuminate\Http\Request): (\Symfony\Component\HttpFoundation\Response) $next
*/
public function handle(Request $request, Closure $next): Response
{
if (Auth::check() && Auth::user()->role == 'admin') {
return $next($request);
}
toast('Anda tidak memiliki akses', 'warning')->position('top')->autoclose(3000);
return redirect()->back();
}
}

View File

@ -0,0 +1,26 @@
<?php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Symfony\Component\HttpFoundation\Response;
class OfficerMiddleware
{
/**
* Handle an incoming request.
*
* @param \Closure(\Illuminate\Http\Request): (\Symfony\Component\HttpFoundation\Response) $next
*/
public function handle(Request $request, Closure $next): Response
{
if (Auth::check() && Auth::user()->role == 'user') {
return $next($request);
}
toast('Anda tidak memiliki akses', 'warning')->position('top')->autoclose(3000);
return redirect()->back();
}
}

View File

@ -0,0 +1,27 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class EvaluationDetail extends Model
{
use HasFactory;
protected $table = 'evaluation_details';
protected $primaryKey = 'id';
protected $guarded = [];
// protected $fillable = [
// 'evaluation_id',
// 'indicator_id',
// 'value',
// 'cf',
// ];
public function evaluation()
{
return $this->belongsTo(Evalutaion::class);
}
}

18
app/Models/Evalutaion.php Normal file
View File

@ -0,0 +1,18 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class Evalutaion extends Model
{
use HasFactory;
protected $table = 'evaluations';
public function land()
{
return $this->belongsTo(Land::class);
}
}

View File

@ -0,0 +1,32 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('evaluations', function (Blueprint $table) {
$table->id();
$table->unsignedBigInteger('land_id');
$table->timestamps();
});
Schema::table('evaluations', function (Blueprint $table) {
$table->foreign('land_id')->references('id')->on('land')->onDelete('cascade');
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('evaluations');
}
};

View File

@ -0,0 +1,36 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('evaluation_details', function (Blueprint $table) {
$table->id();
$table->unsignedBigInteger('evaluation_id');
$table->unsignedBigInteger('indicator_id');
$table->float('value');
$table->float('cf');
$table->timestamps();
});
Schema::table('evaluation_details', function (Blueprint $table) {
$table->foreign('evaluation_id')->references('id')->on('evaluations')->onDelete('cascade');
$table->foreign('indicator_id')->references('id')->on('indicators')->onDelete('cascade');
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('evaluation_details');
}
};

View File

@ -0,0 +1,23 @@
document.addEventListener("DOMContentLoaded", function () {
const inputs = document.querySelectorAll(
"#pH-field, #ketinggian_tempat-field",
"#ketersediaan_air-field",
"#curah_hujan-field"
);
inputs.forEach((input) => {
input.addEventListener("input", function () {
this.value = this.value.replace(/[^0-9.]/g, "");
this.value = this.value.replace(/^(\.)/, "");
if ((this.value.match(/\./g) || []).length > 1) {
this.value = this.value.substring(
0,
this.value.lastIndexOf(".")
);
}
});
});
});
var landField = document.getElementById("lahan-field");
var landVal = new Choices(landField);

View File

@ -0,0 +1,141 @@
@extends('layouts.app')
@push('title', 'Form Penilaian')
@section('content')
<div class="page-content">
<div class="container-fluid">
<!-- start page title -->
<div class="row">
<div class="col-12">
<div class="page-title-box d-sm-flex align-items-center justify-content-between">
<h4 class="mb-sm-0">Form Penilaian</h4>
<div class="page-title-right">
<ol class="breadcrumb m-0">
<li class="breadcrumb-item">
<a href="javascript: void(0);">Menu</a>
</li>
<li class="breadcrumb-item active">Form Penilaian</li>
</ol>
</div>
</div>
</div>
</div>
<!-- end page title -->
<div class="row">
<div class="col-xl-8 col-md-6">
<div class="card">
<div class="card-header">
<h4 class="card-title mb-0">Form Penilaian</h4>
</div>
<form action="{{ route('assesment_form.store') }}" class="needs-validation" method="POST"
novalidate id="add-form">
@csrf
<div class="card-body">
<div class="mb-3">
<label for="" class="form-label">Lahan</label>
<select name="land" class="form-control" id="lahan-field" required>
<option value="" selected disabled>Pilih Lahan</option>
@foreach ($lands as $land)
<option value="{{ $land->id }}">{{ $land->name }}</option>
@endforeach
</select>
<div class="invalid-feedback">
Pilih Lahan
</div>
</div>
<div class="mb-3">
<label for="" class="form-label">pH Tanah</label>
<div class="input-group">
<input type="text" class="form-control" name="1" id="pH-field"
placeholder="Masukan nilai pH Tanah" aria-label="Masukan nilai pH Tanah"
required>
<span class="input-group-text" id="pH-addon">pH</span>
<div class="invalid-feedback">
Masukan nilai pH
</div>
</div>
</div>
<div class="mb-3">
<label for="" class="form-label">Ketinggian Tempat</label>
<div class="input-group">
<input type="text" class="form-control" name="2"
id="ketinggian_tempat-field" placeholder="Masukan nilai Ketinggian Tempat"
aria-label="Masukan nilai Ketinggian Tempat" required>
<span class="input-group-text" id="ketinggian_tempat-addon">m</span>
<div class="invalid-feedback">
Masukan nilai Ketinggian Tempat
</div>
</div>
</div>
<div class="mb-3">
<label for="" class="form-label">Ketersediaan Air</label>
<div class="input-group">
<input type="text" class="form-control" name="3"
id="ketersediaan_air-field" placeholder="Masukan nilai Ketersediaan Air"
aria-label="Masukan nilai Ketersediaan Air" required>
<span class="input-group-text" id="ketersediaan_air-addon">%</span>
<div class="invalid-feedback">
Masukan nilai Ketersediaan Air
</div>
</div>
</div>
<div class="mb-3">
<label for="" class="form-label">Curah Hujan</label>
<div class="input-group">
<input type="text" class="form-control" name="4" id="curah_hujan-field"
placeholder="Masukan nilai Curah Hujan" aria-label="Masukan nilai Curah Hujan"
required>
<span class="input-group-text" id="curah_hujan-addon">mm</span>
<div class="invalid-feedback">
Masukan nilai Curah Hujan
</div>
</div>
</div>
</div>
<div class="card-footer d-flex justify-content-end">
<button type="submit" class="btn btn-success">Hitung</button>
</div>
</form>
</div>
</div>
<div class="col-xl-4 col-md-6">
<div class="card">
<div class="card-header">
<h4 class="card-title mb-0">Hasil Penilaian</h4>
</div>
<form action="">
<div class="card-body">
{{-- @dd(request()) --}}
{{-- <div class="flex-grow-1 ms-3">
<h2 class="mb-0"><span class="counter-value" data-target="197">0</span></h2>
</div> --}}
@isset(request()->session->result)
<h1 class="mb-0"><span class="counter-value"
data-target="{{ request()->session->result }}">0</span>%
</h1>
@endisset
</div>
</form>
</div>
</div>
</div>
</div>
<!-- container-fluid -->
</div>
@push('other-js')
<!-- prismjs plugin -->
<script src="assets/libs/prismjs/prism.js"></script>
<script src="assets/libs/list.js/list.min.js"></script>
<script src="assets/libs/list.pagination.js/list.pagination.min.js"></script>
<!-- listjs init -->
<script src="assets/js/pages/form-validation.init.js"></script>
<script src="assets/js/pages/customJs/assesment-form/index.js"></script>
@endpush
@endsection

View File

@ -66,7 +66,7 @@
</div> </div>
<!-- Theme Settings --> <!-- Theme Settings -->
<div class="offcanvas offcanvas-end border-0" tabindex="-1" id="theme-settings-offcanvas"> {{-- <div class="offcanvas offcanvas-end border-0" tabindex="-1" id="theme-settings-offcanvas">
<div class="d-flex align-items-center bg-primary bg-gradient p-3 offcanvas-header"> <div class="d-flex align-items-center bg-primary bg-gradient p-3 offcanvas-header">
<h5 class="m-0 me-2 text-white">Theme Customizer</h5> <h5 class="m-0 me-2 text-white">Theme Customizer</h5>
@ -590,7 +590,7 @@ class="form-check-input">
</div> </div>
</div> </div>
</div> </div>
</div> </div> --}}
@include('sweetalert::alert') @include('sweetalert::alert')
<!-- JAVASCRIPT --> <!-- JAVASCRIPT -->

View File

@ -86,6 +86,13 @@ class="nav-link {{ request()->routeIs('master_data.aturan.*') ? 'active' : '' }}
data-key="t-dashboards">Dashboards</span> data-key="t-dashboards">Dashboards</span>
</a> </a>
</li> </li>
<li class="nav-item">
<a class="nav-link menu-link {{ request()->routeIs('assesment_form.index') ? 'active' : '' }}"
href="{{ route('assesment_form.index') }}">
<i data-feather="file-text" class="icon-dual"></i> <span
data-key="t-dashboards">Form Penilaian</span>
</a>
</li>
@endif <!-- end Dashboard Menu --> @endif <!-- end Dashboard Menu -->
{{-- <li class="menu-title"><i class="ri-more-fill"></i> <span data-key="t-pages">Pages</span> {{-- <li class="menu-title"><i class="ri-more-fill"></i> <span data-key="t-pages">Pages</span>

View File

@ -1,5 +1,6 @@
<?php <?php
use App\Http\Controllers\AssesmentFormController;
use App\Http\Controllers\Auth\AuthenticatedSessionController; use App\Http\Controllers\Auth\AuthenticatedSessionController;
use App\Http\Controllers\Auth\PasswordResetLinkController; use App\Http\Controllers\Auth\PasswordResetLinkController;
use App\Http\Controllers\Auth\RegisteredUserController; use App\Http\Controllers\Auth\RegisteredUserController;
@ -10,6 +11,7 @@
use App\Http\Controllers\MasterData\RuleController; use App\Http\Controllers\MasterData\RuleController;
use App\Http\Controllers\MasterData\UserController; use App\Http\Controllers\MasterData\UserController;
use Illuminate\Routing\RouteGroup; use Illuminate\Routing\RouteGroup;
use Illuminate\Routing\RouteUrlGenerator;
use Illuminate\Support\Facades\Route; use Illuminate\Support\Facades\Route;
/* /*
@ -56,39 +58,47 @@
Route::middleware(['auth', 'verifiedAcount'])->group(function () { Route::middleware(['auth', 'verifiedAcount'])->group(function () {
Route::post('/logout', [AuthenticatedSessionController::class, 'destroy'])->name('auth.logout'); Route::post('/logout', [AuthenticatedSessionController::class, 'destroy'])->name('auth.logout');
Route::controller(DashboardController::class)->name('dashboard.')->group(function () { Route::middleware('admin')->group(function () {
Route::get('/dashboard-admin', 'admin')->name('admin'); Route::get('/dashboard-admin', [DashboardController::class, 'admin'])->name('dashboard.admin');
Route::get('/dashboard-petugas', 'petugas')->name('petugas');
Route::name('master_data.')->group(function () {
Route::prefix('data-pengguna')->controller(UserController::class)->name('pengguna.')->group(function () {
Route::get('/', 'index')->name('index');
Route::post('/', 'store')->name('store');
Route::put('/{id}', 'update')->name('update');
Route::delete('/{id}', 'destroy')->name('destroy');
});
Route::prefix('data-lahan')->controller(LandController::class)->name('lahan.')->group(function () {
Route::get('/', 'index')->name('index');
Route::post('/', 'store')->name('store');
Route::put('/{id}', 'update')->name('update');
Route::delete('/{id}', 'destroy')->name('destroy');
});
Route::prefix('data-indikator')->controller(IndicatorController::class)->name('indikator.')->group(function () {
Route::get('/', 'index')->name('index');
// Route::post('/', 'store')->name('store');
Route::put('/{id}', 'update')->name('update');
// Route::delete('/{id}', 'destroy')->name('destroy');
});
Route::prefix('data-aturan')->controller(RuleController::class)->name('aturan.')->group(function () {
Route::get('/', 'index')->name('index');
// Route::post('/', 'store')->name('store');
Route::put('/{id}', 'update')->name('update');
// Route::delete('/{id}', 'destroy')->name('destroy');
});
});
}); });
Route::name('master_data.')->group(function () { Route::middleware('officer')->group(function () {
Route::get('/dashboard-petugas', [DashboardController::class, 'petugas'])->name('dashboard.petugas');
Route::prefix('data-pengguna')->controller(UserController::class)->name('pengguna.')->group(function () { Route::prefix('form-penilaian')->controller(AssesmentFormController::class)->name('assesment_form.')->group(function () {
Route::get('/', 'index')->name('index'); Route::get('/', 'index')->name('index');
Route::post('/', 'store')->name('store'); Route::post('/', 'store')->name('store');
Route::put('/{id}', 'update')->name('update');
Route::delete('/{id}', 'destroy')->name('destroy');
});
Route::prefix('data-lahan')->controller(LandController::class)->name('lahan.')->group(function () {
Route::get('/', 'index')->name('index');
Route::post('/', 'store')->name('store');
Route::put('/{id}', 'update')->name('update');
Route::delete('/{id}', 'destroy')->name('destroy');
});
Route::prefix('data-indikator')->controller(IndicatorController::class)->name('indikator.')->group(function () {
Route::get('/', 'index')->name('index');
// Route::post('/', 'store')->name('store');
Route::put('/{id}', 'update')->name('update');
// Route::delete('/{id}', 'destroy')->name('destroy');
});
Route::prefix('data-aturan')->controller(RuleController::class)->name('aturan.')->group(function () {
Route::get('/', 'index')->name('index');
// Route::post('/', 'store')->name('store');
Route::put('/{id}', 'update')->name('update');
// Route::delete('/{id}', 'destroy')->name('destroy');
}); });
}); });
}); });

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long