user:dashboard done
This commit is contained in:
parent
1c8fd53f16
commit
23b28a1590
|
|
@ -0,0 +1,35 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Controllers\User;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Models\InformasiBudidaya;
|
||||
use App\Models\InformasiHamaPenyakit;
|
||||
|
||||
class ArtikelUserController extends Controller
|
||||
{
|
||||
public function budidaya()
|
||||
{
|
||||
$artikels = InformasiBudidaya::published()->latest()->paginate(9);
|
||||
return view('user.artikel.budidaya', compact('artikels'));
|
||||
}
|
||||
|
||||
public function detailBudidaya($slug)
|
||||
{
|
||||
$artikel = InformasiBudidaya::where('slug', $slug)->firstOrFail();
|
||||
return view('user.artikel.detail-budidaya', compact('artikel'));
|
||||
}
|
||||
|
||||
public function hamaPenyakit()
|
||||
{
|
||||
$hama = InformasiHamaPenyakit::published()->where('jenis', 'Hama')->latest()->get();
|
||||
$penyakit = InformasiHamaPenyakit::published()->where('jenis', 'Penyakit')->latest()->get();
|
||||
return view('user.artikel.hama-penyakit', compact('hama', 'penyakit'));
|
||||
}
|
||||
|
||||
public function detailHamaPenyakit($slug)
|
||||
{
|
||||
$artikel = InformasiHamaPenyakit::where('slug', $slug)->firstOrFail();
|
||||
return view('user.artikel.detail-hama-penyakit', compact('artikel'));
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,119 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Controllers\User;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Models\MasterGejala;
|
||||
use App\Models\MasterPenyakit;
|
||||
use App\Models\RuleBasis;
|
||||
use App\Models\RiwayatDiagnosis;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
class DiagnosaController extends Controller
|
||||
{
|
||||
public function index()
|
||||
{
|
||||
$gejalas = MasterGejala::orderBy('id_gejala')->get();
|
||||
return view('user.diagnosa.index', compact('gejalas'));
|
||||
}
|
||||
|
||||
public function proses(Request $request)
|
||||
{
|
||||
$request->validate([
|
||||
'gejala' => 'required|array|min:1',
|
||||
], [
|
||||
'gejala.required' => 'Pilih minimal 1 gejala!',
|
||||
'gejala.min' => 'Pilih minimal 1 gejala!',
|
||||
]);
|
||||
|
||||
$gejalaInput = $request->gejala; // array of id_gejala
|
||||
|
||||
// Ambil semua rule yang relevan
|
||||
$rules = RuleBasis::whereIn('id_gejala', $gejalaInput)->get();
|
||||
|
||||
// Hitung MB dan MD per penyakit dulu
|
||||
$mbPenyakit = [];
|
||||
$mdPenyakit = [];
|
||||
|
||||
foreach ($rules as $rule) {
|
||||
$idPenyakit = $rule->id_penyakit;
|
||||
|
||||
if (!isset($mbPenyakit[$idPenyakit])) {
|
||||
// Gejala pertama
|
||||
$mbPenyakit[$idPenyakit] = $rule->mb;
|
||||
$mdPenyakit[$idPenyakit] = $rule->md;
|
||||
} else {
|
||||
// Kombinasi gejala berikutnya (rumus 2 & 3)
|
||||
$mbPenyakit[$idPenyakit] = $mbPenyakit[$idPenyakit] * $rule->mb;
|
||||
$mdPenyakit[$idPenyakit] = $mdPenyakit[$idPenyakit] + $rule->md * (1 - $mdPenyakit[$idPenyakit]);
|
||||
}
|
||||
}
|
||||
|
||||
// Hitung CF = MB - MD
|
||||
$cfPenyakit = [];
|
||||
foreach ($mbPenyakit as $idPenyakit => $mb) {
|
||||
$cfPenyakit[$idPenyakit] = $mb - $mdPenyakit[$idPenyakit];
|
||||
}
|
||||
|
||||
if (empty($cfPenyakit)) {
|
||||
return redirect()->route('user.diagnosa.index')
|
||||
->with('error', 'Tidak ditemukan penyakit yang cocok dengan gejala yang dipilih.');
|
||||
}
|
||||
|
||||
// Urutkan dari CF tertinggi
|
||||
arsort($cfPenyakit);
|
||||
|
||||
// Ambil data penyakit
|
||||
$hasilDiagnosa = [];
|
||||
foreach ($cfPenyakit as $idPenyakit => $cf) {
|
||||
$penyakit = MasterPenyakit::find($idPenyakit);
|
||||
if ($penyakit) {
|
||||
$hasilDiagnosa[] = [
|
||||
'id_penyakit' => $idPenyakit,
|
||||
'nama_penyakit' => $penyakit->nama_penyakit,
|
||||
'cf' => round($cf, 2),
|
||||
'persentase' => round($cf * 100, 1),
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
$penyakitFinal = $hasilDiagnosa[0]['id_penyakit'];
|
||||
$cfTertinggi = $hasilDiagnosa[0]['cf'];
|
||||
|
||||
// Simpan ke riwayat
|
||||
$riwayat = RiwayatDiagnosis::create([
|
||||
'user_id' => auth()->id(),
|
||||
'tanggal' => now(),
|
||||
'gejala_input' => $gejalaInput,
|
||||
'hasil_diagnosa'=> $hasilDiagnosa,
|
||||
'cf_tertinggi' => $cfTertinggi,
|
||||
'penyakit_final'=> $penyakitFinal,
|
||||
]);
|
||||
|
||||
return redirect()->route('user.diagnosa.hasil', $riwayat->id_diagnosis);
|
||||
}
|
||||
|
||||
public function hasil($id)
|
||||
{
|
||||
$riwayat = RiwayatDiagnosis::with('penyakit')->findOrFail($id);
|
||||
|
||||
// Pastikan hanya pemilik yang bisa lihat
|
||||
if ($riwayat->user_id !== auth()->id()) {
|
||||
abort(403);
|
||||
}
|
||||
|
||||
$gejalaInput = MasterGejala::whereIn('id_gejala', $riwayat->gejala_input)->get();
|
||||
|
||||
return view('user.diagnosa.hasil', compact('riwayat', 'gejalaInput'));
|
||||
}
|
||||
|
||||
public function riwayat()
|
||||
{
|
||||
$riwayats = RiwayatDiagnosis::where('user_id', auth()->id())
|
||||
->with('penyakit')
|
||||
->latest('tanggal')
|
||||
->paginate(10);
|
||||
|
||||
return view('user.diagnosa.riwayat', compact('riwayats'));
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,63 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Controllers\User;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Models\RiwayatDiagnosis;
|
||||
use App\Models\MasterPenyakit;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
class UserDashboardController extends Controller
|
||||
{
|
||||
public function index()
|
||||
{
|
||||
$user = auth()->user();
|
||||
|
||||
// Total diagnosa user
|
||||
$totalDiagnosa = RiwayatDiagnosis::where('user_id', $user->id)->count();
|
||||
|
||||
// Diagnosa bulan ini
|
||||
$diagnosabulanIni = RiwayatDiagnosis::where('user_id', $user->id)
|
||||
->whereMonth('tanggal', now()->month)
|
||||
->whereYear('tanggal', now()->year)
|
||||
->count();
|
||||
|
||||
// Riwayat diagnosa terbaru
|
||||
$riwayatTerbaru = RiwayatDiagnosis::where('user_id', $user->id)
|
||||
->with('penyakit')
|
||||
->latest('tanggal')
|
||||
->take(5)
|
||||
->get();
|
||||
|
||||
// Data chart per bulan (6 bulan terakhir)
|
||||
$chartData = [];
|
||||
for ($i = 5; $i >= 0; $i--) {
|
||||
$bulan = now()->subMonths($i);
|
||||
$chartData[] = [
|
||||
'bulan' => $bulan->format('M Y'),
|
||||
'total' => RiwayatDiagnosis::where('user_id', $user->id)
|
||||
->whereMonth('tanggal', $bulan->month)
|
||||
->whereYear('tanggal', $bulan->year)
|
||||
->count(),
|
||||
];
|
||||
}
|
||||
|
||||
// Statistik penyakit terbanyak didiagnosa user
|
||||
$statistikPenyakit = RiwayatDiagnosis::where('user_id', $user->id)
|
||||
->whereNotNull('penyakit_final')
|
||||
->selectRaw('penyakit_final, count(*) as total')
|
||||
->groupBy('penyakit_final')
|
||||
->with('penyakit')
|
||||
->orderByDesc('total')
|
||||
->take(5)
|
||||
->get();
|
||||
|
||||
return view('user.dashboard', compact(
|
||||
'totalDiagnosa',
|
||||
'diagnosabulanIni',
|
||||
'riwayatTerbaru',
|
||||
'chartData',
|
||||
'statistikPenyakit'
|
||||
));
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Middleware;
|
||||
|
||||
use Closure;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
class IsUser
|
||||
{
|
||||
public function handle(Request $request, Closure $next)
|
||||
{
|
||||
if (auth()->check() && auth()->user()->role === 'user') {
|
||||
return $next($request);
|
||||
}
|
||||
abort(403, 'Akses ditolak.');
|
||||
}
|
||||
}
|
||||
|
|
@ -14,6 +14,7 @@
|
|||
$middleware->alias([
|
||||
'admin' => \App\Http\Middleware\IsAdmin::class,
|
||||
'super_admin' => \App\Http\Middleware\IsSuperAdmin::class,
|
||||
'isUser' => \App\Http\Middleware\IsUser::class,
|
||||
]);
|
||||
})
|
||||
->withExceptions(function (Exceptions $exceptions): void {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
@extends('layouts.admin-app')
|
||||
|
||||
@section('page-title', '📊 Dashboard')
|
||||
@section('page-title', 'Dashboard')
|
||||
@section('page-subtitle', 'Overview statistik sistem pakar')
|
||||
|
||||
@section('content')
|
||||
|
|
@ -9,7 +9,7 @@
|
|||
<div class="absolute right-0 top-0 w-64 h-64 bg-white opacity-5 rounded-full -mr-32 -mt-32"></div>
|
||||
<div class="absolute right-10 bottom-0 w-48 h-48 bg-white opacity-5 rounded-full -mb-24"></div>
|
||||
<div class="relative z-10">
|
||||
<h1 class="text-3xl font-bold mb-2">Selamat Datang Kembali! 👋</h1>
|
||||
<h1 class="text-3xl font-bold mb-2">Selamat Datang Kembali!</h1>
|
||||
<p class="text-green-100 text-lg">{{ Auth::user()->nama }}</p>
|
||||
<p class="text-green-50 mt-4">{{ now()->translatedFormat('l, d F Y') }}</p>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -27,14 +27,14 @@
|
|||
<div class="p-6 border-b border-gray-200">
|
||||
<div class="flex justify-between items-center">
|
||||
<div class="flex items-center">
|
||||
<div class="bg-gradient-to-r from-red-500 to-red-600 rounded-xl p-3 mr-4">
|
||||
<div class="bg-gradient-to-r from-green-500 to-green-600 rounded-xl p-3 mr-4">
|
||||
<svg class="w-6 h-6 text-white" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z"></path>
|
||||
</svg>
|
||||
</div>
|
||||
<h3 class="text-xl font-bold text-gray-800">Daftar Penyakit & Hama Tanaman Kopi</h3>
|
||||
</div>
|
||||
<a href="{{ route('admin.penyakit.create') }}" class="flex items-center px-5 py-3 bg-gradient-to-r from-red-500 to-red-600 text-white font-bold rounded-xl hover:from-red-600 hover:to-red-700 transition-all shadow-lg hover:shadow-xl transform hover:scale-105">
|
||||
<a href="{{ route('admin.penyakit.create') }}" class="flex items-center px-5 py-3 bg-gradient-to-r from-green-500 to-green-600 text-white font-bold rounded-xl hover:from-red-600 hover:to-red-700 transition-all shadow-lg hover:shadow-xl transform hover:scale-105">
|
||||
<svg class="w-5 h-5 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 6v6m0 0v6m0-6h6m-6 0H6"></path>
|
||||
</svg>
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@
|
|||
<!-- Header -->
|
||||
<div class="p-6 border-b border-gray-200">
|
||||
<div class="flex items-center">
|
||||
<div class="bg-gradient-to-r from-purple-500 to-purple-600 rounded-xl p-3 mr-4">
|
||||
<div class="bg-gradient-to-r from-green-500 to-green-600 rounded-xl p-3 mr-4">
|
||||
<svg class="w-6 h-6 text-white" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 6v6m0 0v6m0-6h6m-6 0H6"></path>
|
||||
</svg>
|
||||
|
|
@ -49,7 +49,7 @@
|
|||
<select
|
||||
name="id_penyakit"
|
||||
id="id_penyakit"
|
||||
class="w-full px-4 py-3 border border-gray-300 rounded-xl focus:ring-2 focus:ring-purple-500 focus:border-purple-500 transition @error('id_penyakit') border-red-500 @enderror"
|
||||
class="w-full px-4 py-3 border border-gray-300 rounded-xl focus:ring-2 focus:ring-green-500 focus:border-green-500 transition @error('id_penyakit') border-red-500 @enderror"
|
||||
required
|
||||
>
|
||||
<option value="">-- Pilih Penyakit --</option>
|
||||
|
|
@ -72,7 +72,7 @@ class="w-full px-4 py-3 border border-gray-300 rounded-xl focus:ring-2 focus:rin
|
|||
<select
|
||||
name="id_gejala"
|
||||
id="id_gejala"
|
||||
class="w-full px-4 py-3 border border-gray-300 rounded-xl focus:ring-2 focus:ring-purple-500 focus:border-purple-500 transition @error('id_gejala') border-red-500 @enderror"
|
||||
class="w-full px-4 py-3 border border-gray-300 rounded-xl focus:ring-2 focus:ring-green-500 focus:border-green-500 transition @error('id_gejala') border-red-500 @enderror"
|
||||
required
|
||||
>
|
||||
<option value="">-- Pilih Gejala --</option>
|
||||
|
|
@ -100,7 +100,7 @@ class="w-full px-4 py-3 border border-gray-300 rounded-xl focus:ring-2 focus:rin
|
|||
step="0.01"
|
||||
min="0"
|
||||
max="1"
|
||||
class="w-full px-4 py-3 border border-gray-300 rounded-xl focus:ring-2 focus:ring-purple-500 focus:border-purple-500 transition @error('mb') border-red-500 @enderror"
|
||||
class="w-full px-4 py-3 border border-gray-300 rounded-xl focus:ring-2 focus:ring-green-500 focus:border-green-500 transition @error('mb') border-red-500 @enderror"
|
||||
placeholder="0.00 - 1.00"
|
||||
required
|
||||
oninput="calculateCF()"
|
||||
|
|
@ -124,7 +124,7 @@ class="w-full px-4 py-3 border border-gray-300 rounded-xl focus:ring-2 focus:rin
|
|||
step="0.01"
|
||||
min="0"
|
||||
max="1"
|
||||
class="w-full px-4 py-3 border border-gray-300 rounded-xl focus:ring-2 focus:ring-purple-500 focus:border-purple-500 transition @error('md') border-red-500 @enderror"
|
||||
class="w-full px-4 py-3 border border-gray-300 rounded-xl focus:ring-2 focus:ring-green-500 focus:border-green-500 transition @error('md') border-red-500 @enderror"
|
||||
placeholder="0.00 - 1.00"
|
||||
required
|
||||
oninput="calculateCF()"
|
||||
|
|
@ -140,10 +140,10 @@ class="w-full px-4 py-3 border border-gray-300 rounded-xl focus:ring-2 focus:rin
|
|||
<label class="block text-sm font-semibold text-gray-700 mb-2">
|
||||
CF (Certainty Factor) - Otomatis Dihitung
|
||||
</label>
|
||||
<div class="px-4 py-3 bg-purple-50 border border-purple-200 rounded-xl">
|
||||
<div class="px-4 py-3 bg-green-50 border border-green-200 rounded-xl">
|
||||
<div class="flex items-center justify-between">
|
||||
<span class="text-sm text-gray-700">CF = MB - MD</span>
|
||||
<span id="cf_preview" class="text-2xl font-bold text-purple-600">0.00</span>
|
||||
<span id="cf_preview" class="text-2xl font-bold text-green-600">0.00</span>
|
||||
</div>
|
||||
</div>
|
||||
<p class="mt-1 text-sm text-gray-500">Nilai CF akan otomatis dihitung dari MB - MD</p>
|
||||
|
|
@ -158,7 +158,7 @@ class="w-full px-4 py-3 border border-gray-300 rounded-xl focus:ring-2 focus:rin
|
|||
name="keterangan"
|
||||
id="keterangan"
|
||||
rows="3"
|
||||
class="w-full px-4 py-3 border border-gray-300 rounded-xl focus:ring-2 focus:ring-purple-500 focus:border-purple-500 transition"
|
||||
class="w-full px-4 py-3 border border-gray-300 rounded-xl focus:ring-2 focus:ring-green-500 focus:border-green-500 transition"
|
||||
placeholder="Catatan tambahan tentang rule ini..."
|
||||
>{{ old('keterangan') }}</textarea>
|
||||
</div>
|
||||
|
|
@ -173,7 +173,7 @@ class="px-6 py-3 bg-gray-300 text-gray-700 font-semibold rounded-xl hover:bg-gra
|
|||
</a>
|
||||
{{-- FIX: Tombol Simpan pakai inline style agar warna tidak transparan --}}
|
||||
<button type="submit"
|
||||
style="background: linear-gradient(to right, #8b5cf6, #7c3aed); color: white;"
|
||||
style="background: linear-gradient(to right, #22c55e, #16a34a); color: white;"
|
||||
class="px-6 py-3 font-bold rounded-xl shadow-lg hover:shadow-xl transition-all transform hover:scale-105 flex items-center">
|
||||
<svg class="w-5 h-5 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M8 7H5a2 2 0 00-2 2v9a2 2 0 002 2h14a2 2 0 002-2V9a2 2 0 00-2-2h-3m-1 4l-3 3m0 0l-3-3m3 3V4"></path>
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@
|
|||
<!-- Header -->
|
||||
<div class="p-6 border-b border-gray-200">
|
||||
<div class="flex items-center">
|
||||
<div class="bg-gradient-to-r from-blue-500 to-blue-600 rounded-xl p-3 mr-4">
|
||||
<div class="bg-gradient-to-r from-green-500 to-green-600 rounded-xl p-3 mr-4">
|
||||
<svg class="w-6 h-6 text-white" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M11 5H6a2 2 0 00-2 2v11a2 2 0 002 2h11a2 2 0 002-2v-5m-1.414-9.414a2 2 0 112.828 2.828L11.828 15H9v-2.828l8.586-8.586z"></path>
|
||||
</svg>
|
||||
|
|
@ -83,7 +83,7 @@
|
|||
step="0.01"
|
||||
min="0"
|
||||
max="1"
|
||||
class="w-full px-4 py-3 border border-gray-300 rounded-xl focus:ring-2 focus:ring-blue-500 focus:border-blue-500 transition @error('mb') border-red-500 @enderror"
|
||||
class="w-full px-4 py-3 border border-gray-300 rounded-xl focus:ring-2 focus:ring-green-500 focus:border-green-500 transition @error('mb') border-red-500 @enderror"
|
||||
required
|
||||
oninput="calculateCF()"
|
||||
>
|
||||
|
|
@ -106,7 +106,7 @@ class="w-full px-4 py-3 border border-gray-300 rounded-xl focus:ring-2 focus:rin
|
|||
step="0.01"
|
||||
min="0"
|
||||
max="1"
|
||||
class="w-full px-4 py-3 border border-gray-300 rounded-xl focus:ring-2 focus:ring-blue-500 focus:border-blue-500 transition @error('md') border-red-500 @enderror"
|
||||
class="w-full px-4 py-3 border border-gray-300 rounded-xl focus:ring-2 focus:ring-green-500 focus:border-green-500 transition @error('md') border-red-500 @enderror"
|
||||
required
|
||||
oninput="calculateCF()"
|
||||
>
|
||||
|
|
@ -121,10 +121,10 @@ class="w-full px-4 py-3 border border-gray-300 rounded-xl focus:ring-2 focus:rin
|
|||
<label class="block text-sm font-semibold text-gray-700 mb-2">
|
||||
CF (Certainty Factor) - Otomatis Dihitung
|
||||
</label>
|
||||
<div class="px-4 py-3 bg-blue-50 border border-blue-200 rounded-xl">
|
||||
<div class="px-4 py-3 bg-green-50 border border-green-200 rounded-xl">
|
||||
<div class="flex items-center justify-between">
|
||||
<span class="text-sm text-gray-700">CF = MB - MD</span>
|
||||
<span id="cf_preview" class="text-2xl font-bold text-blue-600">{{ number_format($ruleBasis->cf_pakar, 2) }}</span>
|
||||
<span id="cf_preview" class="text-2xl font-bold text-green-600">{{ number_format($ruleBasis->cf_pakar, 2) }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<p class="mt-1 text-sm text-gray-500">Nilai CF akan otomatis dihitung dari MB - MD</p>
|
||||
|
|
@ -139,7 +139,7 @@ class="w-full px-4 py-3 border border-gray-300 rounded-xl focus:ring-2 focus:rin
|
|||
name="keterangan"
|
||||
id="keterangan"
|
||||
rows="3"
|
||||
class="w-full px-4 py-3 border border-gray-300 rounded-xl focus:ring-2 focus:ring-blue-500 focus:border-blue-500 transition"
|
||||
class="w-full px-4 py-3 border border-gray-300 rounded-xl focus:ring-2 focus:ring-green-500 focus:border-green-500 transition"
|
||||
placeholder="Catatan tambahan tentang rule ini..."
|
||||
>{{ old('keterangan', $ruleBasis->keterangan) }}</textarea>
|
||||
</div>
|
||||
|
|
@ -151,7 +151,7 @@ class="w-full px-4 py-3 border border-gray-300 rounded-xl focus:ring-2 focus:rin
|
|||
<a href="{{ route('admin.rule-basis.index') }}" class="px-6 py-3 bg-gray-300 text-gray-700 font-semibold rounded-xl hover:bg-gray-400 transition">
|
||||
Batal
|
||||
</a>
|
||||
<button type="submit" class="px-6 py-3 bg-gradient-to-r from-blue-500 to-blue-600 text-white font-bold rounded-xl hover:from-blue-600 hover:to-blue-700 transition-all shadow-lg hover:shadow-xl transform hover:scale-105 flex items-center">
|
||||
<button type="submit" class="px-6 py-3 bg-gradient-to-r from-green-500 to-green-600 text-white font-bold rounded-xl hover:from-green-600 hover:to-green-700 transition-all shadow-lg hover:shadow-xl transform hover:scale-105 flex items-center">
|
||||
<svg class="w-5 h-5 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M8 7H5a2 2 0 00-2 2v9a2 2 0 002 2h14a2 2 0 002-2V9a2 2 0 00-2-2h-3m-1 4l-3 3m0 0l-3-3m3 3V4"></path>
|
||||
</svg>
|
||||
|
|
|
|||
|
|
@ -77,7 +77,7 @@
|
|||
<div class="p-6 border-b border-gray-200">
|
||||
<div class="flex justify-between items-center">
|
||||
<div class="flex items-center">
|
||||
<div class="bg-gradient-to-r from-purple-500 to-purple-600 rounded-xl p-3 mr-4">
|
||||
<div class="bg-gradient-to-r from-green-500 to-green-600 rounded-xl p-3 mr-4">
|
||||
<svg class="w-6 h-6 text-white" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-3 7h3m-3 4h3m-6-4h.01M9 16h.01"></path>
|
||||
</svg>
|
||||
|
|
@ -86,7 +86,7 @@
|
|||
</div>
|
||||
{{-- FIX: Tombol Tambah Rule - warna solid purple --}}
|
||||
<a href="{{ route('admin.rule-basis.create') }}"
|
||||
style="background: linear-gradient(to right, #8b5cf6, #7c3aed); color: white;"
|
||||
style="background: linear-gradient(to right, #22c55e, #16a34a); color: white;"
|
||||
class="flex items-center px-5 py-3 font-bold rounded-xl shadow-lg hover:shadow-xl transition-all transform hover:scale-105">
|
||||
<svg class="w-5 h-5 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 6v6m0 0v6m0-6h6m-6 0H6"></path>
|
||||
|
|
@ -101,7 +101,7 @@ class="flex items-center px-5 py-3 font-bold rounded-xl shadow-lg hover:shadow-x
|
|||
<form method="GET" action="{{ route('admin.rule-basis.index') }}" class="flex gap-4">
|
||||
<div class="flex-1">
|
||||
<label for="penyakit" class="block text-sm font-semibold text-gray-700 mb-2">Filter Penyakit</label>
|
||||
<select name="penyakit" id="penyakit" class="w-full px-4 py-2 border border-gray-300 rounded-xl focus:ring-2 focus:ring-purple-500 focus:border-purple-500">
|
||||
<select name="penyakit" id="penyakit" class="w-full px-4 py-2 border border-gray-300 rounded-xl focus:ring-2 focus:ring-green-500 focus:border-green-500">
|
||||
<option value="">Semua Penyakit</option>
|
||||
@foreach($penyakits as $penyakit)
|
||||
<option value="{{ $penyakit->id_penyakit }}" {{ request('penyakit') == $penyakit->id_penyakit ? 'selected' : '' }}>
|
||||
|
|
@ -112,7 +112,7 @@ class="flex items-center px-5 py-3 font-bold rounded-xl shadow-lg hover:shadow-x
|
|||
</div>
|
||||
<div class="flex-1">
|
||||
<label for="gejala" class="block text-sm font-semibold text-gray-700 mb-2">Filter Gejala</label>
|
||||
<select name="gejala" id="gejala" class="w-full px-4 py-2 border border-gray-300 rounded-xl focus:ring-2 focus:ring-purple-500 focus:border-purple-500">
|
||||
<select name="gejala" id="gejala" class="w-full px-4 py-2 border border-gray-300 rounded-xl focus:ring-2 focus:ring-green-500 focus:border-green-500">
|
||||
<option value="">Semua Gejala</option>
|
||||
@foreach($gejalas as $gejala)
|
||||
<option value="{{ $gejala->id_gejala }}" {{ request('gejala') == $gejala->id_gejala ? 'selected' : '' }}>
|
||||
|
|
@ -122,7 +122,7 @@ class="flex items-center px-5 py-3 font-bold rounded-xl shadow-lg hover:shadow-x
|
|||
</select>
|
||||
</div>
|
||||
<div class="flex items-end gap-2">
|
||||
<button type="submit" style="background-color: #8b5cf6; color: white;" class="px-6 py-2 font-semibold rounded-xl hover:opacity-90 transition">
|
||||
<button type="submit" style="background-color: #22c55e; color: white;" class="px-6 py-2 font-semibold rounded-xl hover:opacity-90 transition">
|
||||
Filter
|
||||
</button>
|
||||
@if(request('penyakit') || request('gejala'))
|
||||
|
|
|
|||
|
|
@ -58,27 +58,7 @@
|
|||
animation: float 3s ease-in-out infinite;
|
||||
}
|
||||
|
||||
/* Menu Item Active Indicator */
|
||||
.menu-item {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.menu-item::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
height: 100%;
|
||||
width: 4px;
|
||||
background: linear-gradient(to bottom, #5FA357, #C1FA70);
|
||||
transform: translateX(-100%);
|
||||
transition: transform 0.3s ease;
|
||||
}
|
||||
|
||||
.menu-item:hover::before,
|
||||
.menu-item.active::before {
|
||||
transform: translateX(0);
|
||||
}
|
||||
|
||||
|
||||
/* Page Fade In Animation */
|
||||
@keyframes fadeInUp {
|
||||
|
|
@ -150,8 +130,8 @@ class="p-2 rounded-lg hover:bg-gray-700 transition-colors"
|
|||
<a href="{{ route('admin.dashboard') }}"
|
||||
class="menu-item flex items-center px-4 py-3 rounded-xl hover:bg-gray-700 {{ request()->routeIs('admin.dashboard') ? 'active bg-gray-700' : '' }} group">
|
||||
<div class="flex items-center flex-1">
|
||||
<div class="w-10 h-10 flex items-center justify-center rounded-lg bg-blue-500/20 group-hover:bg-blue-500/30 transition-colors">
|
||||
<svg class="w-5 h-5 text-blue-400" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<div class="w-10 h-10 flex items-center justify-center rounded-lg bg-green-500/20 group-hover:bg-green-500/30 transition-colors">
|
||||
<svg class="w-5 h-5 text-green-400" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M3 12l2-2m0 0l7-7 7 7M5 10v10a1 1 0 001 1h3m10-11l2 2m-2-2v10a1 1 0 01-1 1h-3m-6 0a1 1 0 001-1v-4a1 1 0 011-1h2a1 1 0 011 1v4a1 1 0 001 1m-6 0h6"></path>
|
||||
</svg>
|
||||
</div>
|
||||
|
|
@ -163,8 +143,8 @@ class="menu-item flex items-center px-4 py-3 rounded-xl hover:bg-gray-700 {{ req
|
|||
<a href="{{ route('admin.penyakit.index') }}"
|
||||
class="menu-item flex items-center px-4 py-3 rounded-xl hover:bg-gray-700 {{ request()->routeIs('admin.penyakit.*') ? 'active bg-gray-700' : '' }} group">
|
||||
<div class="flex items-center flex-1">
|
||||
<div class="w-10 h-10 flex items-center justify-center rounded-lg bg-red-500/20 group-hover:bg-red-500/30 transition-colors">
|
||||
<svg class="w-5 h-5 text-red-400" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<div class="w-10 h-10 flex items-center justify-center rounded-lg bg-green-500/20 group-hover:bg-green-500/30 transition-colors">
|
||||
<svg class="w-5 h-5 text-green-400" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z"></path>
|
||||
</svg>
|
||||
</div>
|
||||
|
|
@ -186,11 +166,11 @@ class="menu-item flex items-center px-4 py-3 rounded-xl hover:bg-gray-700 {{ req
|
|||
</a>
|
||||
|
||||
<!-- Rule Basis Management -->
|
||||
<a href="{{ route('admin.rule-basis.index') }}"
|
||||
<a href="{{ route('admin.rule-basis.index') }}"
|
||||
class="menu-item flex items-center px-4 py-3 rounded-xl hover:bg-gray-700 {{ request()->routeIs('admin.rule-basis.*') ? 'active bg-gray-700' : '' }} group">
|
||||
<div class="flex items-center flex-1">
|
||||
<div class="w-10 h-10 flex items-center justify-center rounded-lg bg-purple-500/20 group-hover:bg-purple-500/30 transition-colors">
|
||||
<svg class="w-5 h-5 text-purple-400" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<div class="w-10 h-10 flex items-center justify-center rounded-lg bg-green-500/20 group-hover:bg-green-500/30 transition-colors">
|
||||
<svg class="w-5 h-5 text-green-400" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-3 7h3m-3 4h3m-6-4h.01M9 16h.01"></path>
|
||||
</svg>
|
||||
</div>
|
||||
|
|
@ -205,8 +185,8 @@ class="menu-item flex items-center px-4 py-3 rounded-xl hover:bg-gray-700 {{ req
|
|||
<button @click="informasiOpen = !informasiOpen"
|
||||
class="menu-item w-full flex items-center px-4 py-3 rounded-xl hover:bg-gray-700 {{ request()->routeIs('admin.artikel-budidaya.*') || request()->routeIs('admin.artikel-hama-penyakit.*') ? 'active bg-gray-700' : '' }} group">
|
||||
<div class="flex items-center flex-1">
|
||||
<div class="w-10 h-10 flex items-center justify-center rounded-lg bg-yellow-500/20 group-hover:bg-yellow-500/30 transition-colors">
|
||||
<svg class="w-5 h-5 text-yellow-400" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<div class="w-10 h-10 flex items-center justify-center rounded-lg bg-green-500/20 group-hover:bg-green-500/30 transition-colors">
|
||||
<svg class="w-5 h-5 text-green-400" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 20H5a2 2 0 01-2-2V6a2 2 0 012-2h10a2 2 0 012 2v1m2 13a2 2 0 01-2-2V7m2 13a2 2 0 002-2V9a2 2 0 00-2-2h-2m-4-3H9M7 16h6M7 8h6v4H7V8z"></path>
|
||||
</svg>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,228 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}" x-data="{ sidebarOpen: true }" x-cloak>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<meta name="csrf-token" content="{{ csrf_token() }}">
|
||||
|
||||
<title>{{ config('app.name', 'Laravel') }} - Coffee Expert</title>
|
||||
|
||||
<link rel="preconnect" href="https://fonts.bunny.net">
|
||||
<link href="https://fonts.bunny.net/css?family=plus-jakarta-sans:400,500,600,700,800&display=swap" rel="stylesheet" />
|
||||
|
||||
@vite(['resources/css/app.css', 'resources/js/app.js'])
|
||||
|
||||
<script defer src="https://cdn.jsdelivr.net/npm/alpinejs@3.x.x/dist/cdn.min.js"></script>
|
||||
|
||||
<style>
|
||||
[x-cloak] { display: none !important; }
|
||||
* { font-family: 'Plus Jakarta Sans', sans-serif; }
|
||||
|
||||
::-webkit-scrollbar { width: 8px; height: 8px; }
|
||||
::-webkit-scrollbar-track { background: #f1f1f1; }
|
||||
::-webkit-scrollbar-thumb { background: #5FA357; border-radius: 4px; }
|
||||
::-webkit-scrollbar-thumb:hover { background: #4a8345; }
|
||||
|
||||
.sidebar-transition {
|
||||
transition: width 0.3s cubic-bezier(0.4, 0, 0.2, 1), margin-left 0.3s cubic-bezier(0.4, 0, 0.2, 1);
|
||||
}
|
||||
|
||||
@keyframes float {
|
||||
0%, 100% { transform: translateY(0px); }
|
||||
50% { transform: translateY(-5px); }
|
||||
}
|
||||
.logo-float { animation: float 3s ease-in-out infinite; }
|
||||
|
||||
@keyframes fadeInUp {
|
||||
from { opacity: 0; transform: translateY(20px); }
|
||||
to { opacity: 1; transform: translateY(0); }
|
||||
}
|
||||
.page-content { animation: fadeInUp 0.5s ease-out; }
|
||||
|
||||
@keyframes pulse {
|
||||
0%, 100% { opacity: 1; }
|
||||
50% { opacity: 0.5; }
|
||||
}
|
||||
.badge-pulse { animation: pulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite; }
|
||||
</style>
|
||||
|
||||
@stack('styles')
|
||||
</head>
|
||||
<body class="font-sans antialiased bg-gray-50">
|
||||
<div class="min-h-screen flex">
|
||||
|
||||
<!-- Sidebar -->
|
||||
<aside
|
||||
:class="sidebarOpen ? 'w-64' : 'w-20'"
|
||||
class="sidebar-transition bg-gradient-to-b from-gray-900 via-gray-800 to-gray-900 text-white fixed h-full z-30 flex flex-col shadow-2xl"
|
||||
>
|
||||
<!-- Logo -->
|
||||
<div class="p-6 border-b border-gray-700">
|
||||
<div class="flex items-center justify-between">
|
||||
<div x-show="sidebarOpen" class="flex items-center space-x-3">
|
||||
<div class="logo-float">
|
||||
<div class="w-10 h-10 bg-gradient-to-br from-green-400 to-green-600 rounded-xl flex items-center justify-center shadow-lg">
|
||||
<svg class="w-6 h-6 text-white" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2.5" d="M9 12l2 2 4-4m5.618-4.016A11.955 11.955 0 0112 2.944a11.955 11.955 0 01-8.618 3.04A12.02 12.02 0 003 9c0 5.591 3.824 10.29 9 11.622 5.176-1.332 9-6.03 9-11.622 0-1.042-.133-2.052-.382-3.016z"></path>
|
||||
</svg>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<h1 class="text-lg font-bold bg-gradient-to-r from-green-400 to-green-200 bg-clip-text text-transparent">Coffee Expert</h1>
|
||||
<p class="text-xs text-gray-400">Sistem Pakar Kopi</p>
|
||||
</div>
|
||||
</div>
|
||||
<button @click="sidebarOpen = !sidebarOpen" class="p-2 rounded-lg hover:bg-gray-700 transition-colors">
|
||||
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 6h16M4 12h16M4 18h16"></path>
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Navigation -->
|
||||
<nav class="flex-1 px-4 py-6 space-y-2 overflow-y-auto">
|
||||
|
||||
<!-- Dashboard -->
|
||||
<a href="{{ route('user.dashboard') }}"
|
||||
class="flex items-center px-4 py-3 rounded-xl hover:bg-gray-700 {{ request()->routeIs('user.dashboard') ? 'bg-gray-700' : '' }} group">
|
||||
<div class="flex items-center flex-1">
|
||||
<div class="w-10 h-10 flex items-center justify-center rounded-lg bg-blue-500/20 group-hover:bg-blue-500/30 transition-colors">
|
||||
<svg class="w-5 h-5 text-blue-400" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M3 12l2-2m0 0l7-7 7 7M5 10v10a1 1 0 001 1h3m10-11l2 2m-2-2v10a1 1 0 01-1 1h-3m-6 0a1 1 0 001-1v-4a1 1 0 011-1h2a1 1 0 011 1v4a1 1 0 001 1m-6 0h6"></path>
|
||||
</svg>
|
||||
</div>
|
||||
<span x-show="sidebarOpen" class="ml-3 font-semibold">Dashboard</span>
|
||||
</div>
|
||||
</a>
|
||||
|
||||
<!-- Diagnosa -->
|
||||
<div x-data="{ diagnosaOpen: {{ request()->routeIs('user.diagnosa.*') ? 'true' : 'false' }} }">
|
||||
<button @click="diagnosaOpen = !diagnosaOpen"
|
||||
class="w-full flex items-center px-4 py-3 rounded-xl hover:bg-gray-700 {{ request()->routeIs('user.diagnosa.*') ? 'bg-gray-700' : '' }} group">
|
||||
<div class="flex items-center flex-1">
|
||||
<div class="w-10 h-10 flex items-center justify-center rounded-lg bg-green-500/20 group-hover:bg-green-500/30 transition-colors">
|
||||
<svg class="w-5 h-5 text-green-400" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path>
|
||||
</svg>
|
||||
</div>
|
||||
<span x-show="sidebarOpen" class="ml-3 font-semibold">Diagnosa</span>
|
||||
</div>
|
||||
<svg x-show="sidebarOpen" :class="diagnosaOpen ? 'rotate-180' : ''" class="w-4 h-4 text-gray-400 transition-transform duration-200" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7"></path>
|
||||
</svg>
|
||||
</button>
|
||||
<div x-show="diagnosaOpen && sidebarOpen"
|
||||
x-transition:enter="transition ease-out duration-200"
|
||||
x-transition:enter-start="opacity-0 -translate-y-2"
|
||||
x-transition:enter-end="opacity-100 translate-y-0"
|
||||
class="mt-1 ml-6 pl-4 border-l-2 border-gray-600 space-y-1">
|
||||
<a href="{{ route('user.diagnosa.index') }}"
|
||||
class="flex items-center px-3 py-2 rounded-lg hover:bg-gray-700 {{ request()->routeIs('user.diagnosa.index') ? 'bg-gray-700 text-white' : 'text-gray-400' }} group transition-colors">
|
||||
<span class="text-sm font-medium group-hover:text-white">Mulai Diagnosa</span>
|
||||
</a>
|
||||
<a href="{{ route('user.diagnosa.riwayat') }}"
|
||||
class="flex items-center px-3 py-2 rounded-lg hover:bg-gray-700 {{ request()->routeIs('user.diagnosa.riwayat') ? 'bg-gray-700 text-white' : 'text-gray-400' }} group transition-colors">
|
||||
<span class="text-sm font-medium group-hover:text-white">Riwayat Diagnosa</span>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Artikel -->
|
||||
<div x-data="{ artikelOpen: {{ request()->routeIs('user.artikel.*') ? 'true' : 'false' }} }">
|
||||
<button @click="artikelOpen = !artikelOpen"
|
||||
class="w-full flex items-center px-4 py-3 rounded-xl hover:bg-gray-700 {{ request()->routeIs('user.artikel.*') ? 'bg-gray-700' : '' }} group">
|
||||
<div class="flex items-center flex-1">
|
||||
<div class="w-10 h-10 flex items-center justify-center rounded-lg bg-yellow-500/20 group-hover:bg-yellow-500/30 transition-colors">
|
||||
<svg class="w-5 h-5 text-yellow-400" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 20H5a2 2 0 01-2-2V6a2 2 0 012-2h10a2 2 0 012 2v1m2 13a2 2 0 01-2-2V7m2 13a2 2 0 002-2V9a2 2 0 00-2-2h-2m-4-3H9M7 16h6M7 8h6v4H7V8z"></path>
|
||||
</svg>
|
||||
</div>
|
||||
<span x-show="sidebarOpen" class="ml-3 font-semibold">Artikel</span>
|
||||
</div>
|
||||
<svg x-show="sidebarOpen" :class="artikelOpen ? 'rotate-180' : ''" class="w-4 h-4 text-gray-400 transition-transform duration-200" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7"></path>
|
||||
</svg>
|
||||
</button>
|
||||
<div x-show="artikelOpen && sidebarOpen"
|
||||
x-transition:enter="transition ease-out duration-200"
|
||||
x-transition:enter-start="opacity-0 -translate-y-2"
|
||||
x-transition:enter-end="opacity-100 translate-y-0"
|
||||
class="mt-1 ml-6 pl-4 border-l-2 border-gray-600 space-y-1">
|
||||
<a href="{{ route('user.artikel.budidaya') }}"
|
||||
class="flex items-center px-3 py-2 rounded-lg hover:bg-gray-700 {{ request()->routeIs('user.artikel.budidaya*') ? 'bg-gray-700 text-white' : 'text-gray-400' }} group transition-colors">
|
||||
<span class="text-sm font-medium group-hover:text-white">Budidaya</span>
|
||||
</a>
|
||||
<a href="{{ route('user.artikel.hama-penyakit') }}"
|
||||
class="flex items-center px-3 py-2 rounded-lg hover:bg-gray-700 {{ request()->routeIs('user.artikel.hama-penyakit*') ? 'bg-gray-700 text-white' : 'text-gray-400' }} group transition-colors">
|
||||
<span class="text-sm font-medium group-hover:text-white">Hama & Penyakit</span>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</nav>
|
||||
|
||||
<!-- Logout -->
|
||||
<div class="p-4 border-t border-gray-700">
|
||||
<form method="POST" action="{{ route('logout') }}">
|
||||
@csrf
|
||||
<button type="submit" class="w-full flex items-center px-4 py-3 rounded-xl hover:bg-red-600/20 group">
|
||||
<div class="flex items-center flex-1">
|
||||
<div class="w-10 h-10 flex items-center justify-center rounded-lg bg-red-500/20 group-hover:bg-red-500/30 transition-colors">
|
||||
<svg class="w-5 h-5 text-red-400" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M17 16l4-4m0 0l-4-4m4 4H7m6 4v1a3 3 0 01-3 3H6a3 3 0 01-3-3V7a3 3 0 013-3h4a3 3 0 013 3v1"></path>
|
||||
</svg>
|
||||
</div>
|
||||
<span x-show="sidebarOpen" class="ml-3 font-semibold text-red-400">Logout</span>
|
||||
</div>
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
</aside>
|
||||
|
||||
<!-- Main Content -->
|
||||
<div :class="sidebarOpen ? 'ml-64' : 'ml-20'" class="flex-1 sidebar-transition">
|
||||
|
||||
<!-- Header -->
|
||||
<header class="bg-white border-b border-gray-200 fixed top-0 right-0 z-20 shadow-sm" :class="sidebarOpen ? 'left-64' : 'left-20'" style="transition: left 0.3s cubic-bezier(0.4, 0, 0.2, 1);">
|
||||
<div class="px-8 py-4">
|
||||
<div class="flex items-center justify-between">
|
||||
<div>
|
||||
<h2 class="text-2xl font-bold text-gray-800">@yield('page-title', 'Dashboard')</h2>
|
||||
<p class="text-sm text-gray-500 mt-1">@yield('page-subtitle', 'Sistem Pakar Diagnosa Penyakit Tanaman Kopi')</p>
|
||||
</div>
|
||||
<div class="flex items-center space-x-4">
|
||||
<!-- Profile -->
|
||||
<a href="{{ route('profile.edit') }}" class="flex items-center space-x-3 px-3 py-2 rounded-xl bg-gradient-to-r from-green-50 to-green-100 hover:from-green-100 hover:to-green-200 transition-all">
|
||||
<div class="w-10 h-10 rounded-full bg-gradient-to-br from-green-400 to-green-600 flex items-center justify-center text-white font-bold shadow-lg">
|
||||
{{ substr(Auth::user()->nama, 0, 1) }}
|
||||
</div>
|
||||
<div class="text-left">
|
||||
<p class="text-sm font-bold text-gray-800">{{ Auth::user()->nama }}</p>
|
||||
<p class="text-xs text-green-600 font-semibold uppercase">User</p>
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<!-- Page Content -->
|
||||
<main class="pt-28">
|
||||
<div class="p-8 page-content">
|
||||
@yield('content')
|
||||
</div>
|
||||
</main>
|
||||
|
||||
<!-- Footer -->
|
||||
<footer class="px-8 py-6 bg-white border-t border-gray-200">
|
||||
<div class="text-center text-sm text-gray-600">
|
||||
© {{ date('Y') }} Coffee Expert System. All rights reserved.
|
||||
</div>
|
||||
</footer>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@stack('scripts')
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
@extends('layouts.admin-app')
|
||||
@extends(auth()->user()->role === 'admin' || auth()->user()->role === 'super_admin' ? 'layouts.admin-app' : 'layouts.user-app')
|
||||
|
||||
@section('page-title', '👤 Profile Settings')
|
||||
@section('page-subtitle', 'Kelola informasi profil Anda')
|
||||
|
|
|
|||
|
|
@ -0,0 +1,242 @@
|
|||
@extends('layouts.user-app')
|
||||
|
||||
@section('page-title', 'Dashboard')
|
||||
@section('page-subtitle', 'Selamat datang di Coffee Expert System')
|
||||
|
||||
@section('content')
|
||||
|
||||
<!-- Welcome Banner -->
|
||||
<div class="bg-gradient-to-r from-green-600 to-green-400 rounded-2xl p-6 mb-8 text-white shadow-lg">
|
||||
<div class="flex items-center justify-between">
|
||||
<div>
|
||||
<h2 class="text-2xl font-bold mb-1">Halo, {{ Auth::user()->nama }}!</h2>
|
||||
<p class="text-green-100 text-sm">Selamat datang kembali di sistem pakar kopi. Apa yang ingin kamu lakukan hari ini?</p>
|
||||
<p id="realtime-clock" class="text-green-200 text-xs mt-2 font-medium"></p>
|
||||
</div>
|
||||
<div class="hidden md:block">
|
||||
<svg class="w-20 h-20 text-green-200 opacity-50" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="1" d="M9 12l2 2 4-4m5.618-4.016A11.955 11.955 0 0112 2.944a11.955 11.955 0 01-8.618 3.04A12.02 12.02 0 003 9c0 5.591 3.824 10.29 9 11.622 5.176-1.332 9-6.03 9-11.622 0-1.042-.133-2.052-.382-3.016z"></path>
|
||||
</svg>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex space-x-3 mt-4">
|
||||
<a href="{{ route('user.diagnosa.index') }}" class="px-4 py-2 bg-white text-green-700 font-bold rounded-xl text-sm hover:bg-green-50 transition shadow">
|
||||
Mulai Diagnosa
|
||||
</a>
|
||||
<a href="{{ route('user.artikel.budidaya') }}" class="px-4 py-2 bg-green-700 text-white font-bold rounded-xl text-sm hover:bg-green-800 transition">
|
||||
Baca Artikel
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Stats Cards -->
|
||||
<div class="grid grid-cols-1 md:grid-cols-3 gap-6 mb-8">
|
||||
<!-- Total Diagnosa -->
|
||||
<div class="bg-white rounded-2xl shadow-lg p-6">
|
||||
<div class="flex items-center justify-between">
|
||||
<div>
|
||||
<p class="text-sm text-gray-500 font-medium">Total Diagnosa</p>
|
||||
<p class="text-3xl font-bold text-gray-800 mt-1">{{ $totalDiagnosa }}</p>
|
||||
<p class="text-xs text-gray-400 mt-1">Sepanjang waktu</p>
|
||||
</div>
|
||||
<div class="w-14 h-14 bg-blue-100 rounded-xl flex items-center justify-center">
|
||||
<svg class="w-7 h-7 text-blue-500" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path>
|
||||
</svg>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Diagnosa Bulan Ini -->
|
||||
<div class="bg-white rounded-2xl shadow-lg p-6">
|
||||
<div class="flex items-center justify-between">
|
||||
<div>
|
||||
<p class="text-sm text-gray-500 font-medium">Diagnosa Bulan Ini</p>
|
||||
<p class="text-3xl font-bold text-gray-800 mt-1">{{ $diagnosabulanIni }}</p>
|
||||
<p class="text-xs text-gray-400 mt-1">{{ now()->format('F Y') }}</p>
|
||||
</div>
|
||||
<div class="w-14 h-14 bg-green-100 rounded-xl flex items-center justify-center">
|
||||
<svg class="w-7 h-7 text-green-500" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M8 7V3m8 4V3m-9 8h10M5 21h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v12a2 2 0 002 2z"></path>
|
||||
</svg>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Diagnosa Terakhir -->
|
||||
<div class="bg-white rounded-2xl shadow-lg p-6">
|
||||
<div class="flex items-center justify-between">
|
||||
<div>
|
||||
<p class="text-sm text-gray-500 font-medium">Diagnosa Terakhir</p>
|
||||
@if($riwayatTerbaru->first())
|
||||
<p class="text-sm font-bold text-gray-800 mt-1">{{ $riwayatTerbaru->first()->penyakit->nama_penyakit ?? '-' }}</p>
|
||||
<p class="text-xs text-gray-400 mt-1">{{ $riwayatTerbaru->first()->tanggal->format('d M Y') }}</p>
|
||||
@else
|
||||
<p class="text-sm font-bold text-gray-800 mt-1">Belum ada</p>
|
||||
<p class="text-xs text-gray-400 mt-1">-</p>
|
||||
@endif
|
||||
</div>
|
||||
<div class="w-14 h-14 bg-yellow-100 rounded-xl flex items-center justify-center">
|
||||
<svg class="w-7 h-7 text-yellow-500" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 8v4l3 3m6-3a9 9 0 11-18 0 9 9 0 0118 0z"></path>
|
||||
</svg>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Chart & Statistik -->
|
||||
<div class="grid grid-cols-1 lg:grid-cols-3 gap-6 mb-8">
|
||||
<!-- Line Chart -->
|
||||
<div class="lg:col-span-2 bg-white rounded-2xl shadow-lg p-6">
|
||||
<h3 class="text-lg font-bold text-gray-800 mb-4">Aktivitas Diagnosa (6 Bulan Terakhir)</h3>
|
||||
<div style="height: 250px;">
|
||||
<canvas id="lineChart"></canvas>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Pie Chart -->
|
||||
<div class="bg-white rounded-2xl shadow-lg p-6">
|
||||
<h3 class="text-lg font-bold text-gray-800 mb-4">Distribusi Penyakit</h3>
|
||||
@if($statistikPenyakit->count() > 0)
|
||||
<div style="height: 250px;">
|
||||
<canvas id="pieChart"></canvas>
|
||||
</div>
|
||||
@else
|
||||
<div class="flex flex-col items-center justify-center h-40 text-gray-400">
|
||||
<svg class="w-12 h-12 mb-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 19v-6a2 2 0 00-2-2H5a2 2 0 00-2 2v6a2 2 0 002 2h2a2 2 0 002-2zm0 0V9a2 2 0 012-2h2a2 2 0 012 2v10m-6 0a2 2 0 002 2h2a2 2 0 002-2m0 0V5a2 2 0 012-2h2a2 2 0 012 2v14a2 2 0 01-2 2h-2a2 2 0 01-2-2z"></path>
|
||||
</svg>
|
||||
<p class="text-sm">Belum ada data</p>
|
||||
</div>
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Tabel Statistik & Riwayat Terbaru -->
|
||||
<div class="grid grid-cols-1 lg:grid-cols-2 gap-6">
|
||||
|
||||
<!-- Statistik Penyakit -->
|
||||
<div class="bg-white rounded-2xl shadow-lg p-6">
|
||||
<h3 class="text-lg font-bold text-gray-800 mb-4">Statistik Penyakit Terdiagnosa</h3>
|
||||
@if($statistikPenyakit->count() > 0)
|
||||
<div class="space-y-3">
|
||||
@foreach($statistikPenyakit as $stat)
|
||||
<div class="flex items-center justify-between">
|
||||
<div class="flex items-center space-x-3">
|
||||
<div class="w-3 h-3 rounded-full bg-green-500"></div>
|
||||
<span class="text-sm font-medium text-gray-700">{{ $stat->penyakit->nama_penyakit ?? $stat->penyakit_final }}</span>
|
||||
</div>
|
||||
<div class="flex items-center space-x-2">
|
||||
<div class="w-24 bg-gray-200 rounded-full h-2">
|
||||
<div class="bg-green-500 h-2 rounded-full" style="width: {{ $totalDiagnosa > 0 ? ($stat->total / $totalDiagnosa * 100) : 0 }}%"></div>
|
||||
</div>
|
||||
<span class="text-sm font-bold text-gray-800">{{ $stat->total }}x</span>
|
||||
</div>
|
||||
</div>
|
||||
@endforeach
|
||||
</div>
|
||||
@else
|
||||
<div class="text-center text-gray-400 py-8">
|
||||
<p class="text-sm">Belum ada data statistik</p>
|
||||
</div>
|
||||
@endif
|
||||
</div>
|
||||
|
||||
<!-- Riwayat Terbaru -->
|
||||
<div class="bg-white rounded-2xl shadow-lg p-6">
|
||||
<div class="flex items-center justify-between mb-4">
|
||||
<h3 class="text-lg font-bold text-gray-800">Riwayat Terbaru</h3>
|
||||
<a href="{{ route('user.diagnosa.riwayat') }}" class="text-xs text-green-600 font-semibold hover:underline">Lihat Semua</a>
|
||||
</div>
|
||||
@forelse($riwayatTerbaru as $riwayat)
|
||||
<div class="flex items-center justify-between py-3 border-b border-gray-100 last:border-0">
|
||||
<div>
|
||||
<p class="text-sm font-semibold text-gray-800">{{ $riwayat->penyakit->nama_penyakit ?? '-' }}</p>
|
||||
<p class="text-xs text-gray-400">{{ $riwayat->tanggal->format('d M Y, H:i') }}</p>
|
||||
</div>
|
||||
<div class="text-right">
|
||||
<span class="px-2 py-1 text-xs font-bold rounded-full
|
||||
{{ $riwayat->cf_tertinggi >= 0.8 ? 'bg-red-100 text-red-700' : ($riwayat->cf_tertinggi >= 0.5 ? 'bg-yellow-100 text-yellow-700' : 'bg-green-100 text-green-700') }}">
|
||||
{{ round($riwayat->cf_tertinggi * 100, 1) }}%
|
||||
</span>
|
||||
<a href="{{ route('user.diagnosa.hasil', $riwayat->id_diagnosis) }}" class="block text-xs text-blue-500 hover:underline mt-1">Detail</a>
|
||||
</div>
|
||||
</div>
|
||||
@empty
|
||||
<div class="text-center text-gray-400 py-8">
|
||||
<p class="text-sm">Belum ada riwayat diagnosa</p>
|
||||
<a href="{{ route('user.diagnosa.index') }}" class="text-green-600 text-sm font-semibold hover:underline">Mulai diagnosa sekarang</a>
|
||||
</div>
|
||||
@endforelse
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@endsection
|
||||
|
||||
@push('scripts')
|
||||
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
|
||||
<script>
|
||||
// Line Chart
|
||||
const lineCtx = document.getElementById('lineChart').getContext('2d');
|
||||
new Chart(lineCtx, {
|
||||
type: 'line',
|
||||
data: {
|
||||
labels: {!! json_encode(array_column($chartData, 'bulan')) !!},
|
||||
datasets: [{
|
||||
label: 'Jumlah Diagnosa',
|
||||
data: {!! json_encode(array_column($chartData, 'total')) !!},
|
||||
borderColor: '#5FA357',
|
||||
backgroundColor: 'rgba(95, 163, 87, 0.1)',
|
||||
borderWidth: 3,
|
||||
fill: true,
|
||||
tension: 0.4,
|
||||
pointBackgroundColor: '#5FA357',
|
||||
pointRadius: 5,
|
||||
}]
|
||||
},
|
||||
options: {
|
||||
responsive: true,
|
||||
maintainAspectRatio: false,
|
||||
plugins: { legend: { display: false } },
|
||||
scales: {
|
||||
y: { beginAtZero: true, ticks: { stepSize: 1 } }
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Pie Chart
|
||||
@if($statistikPenyakit->count() > 0)
|
||||
const pieCtx = document.getElementById('pieChart').getContext('2d');
|
||||
new Chart(pieCtx, {
|
||||
type: 'doughnut',
|
||||
data: {
|
||||
labels: {!! json_encode($statistikPenyakit->map(fn($s) => $s->penyakit->nama_penyakit ?? $s->penyakit_final)) !!},
|
||||
datasets: [{
|
||||
data: {!! json_encode($statistikPenyakit->pluck('total')) !!},
|
||||
backgroundColor: ['#5FA357', '#C1FA70', '#3B82F6', '#F59E0B', '#EF4444'],
|
||||
borderWidth: 0,
|
||||
}]
|
||||
},
|
||||
options: {
|
||||
responsive: true,
|
||||
maintainAspectRatio: false,
|
||||
plugins: {
|
||||
legend: { position: 'bottom', labels: { font: { size: 11 } } }
|
||||
}
|
||||
}
|
||||
});
|
||||
@endif
|
||||
// Real time clock
|
||||
function updateClock() {
|
||||
const now = new Date();
|
||||
const options = {
|
||||
weekday: 'long', year: 'numeric', month: 'long', day: 'numeric',
|
||||
hour: '2-digit', minute: '2-digit', second: '2-digit'
|
||||
};
|
||||
document.getElementById('realtime-clock').textContent = now.toLocaleDateString('id-ID', options);
|
||||
}
|
||||
updateClock();
|
||||
setInterval(updateClock, 1000);
|
||||
</script>
|
||||
@endpush
|
||||
|
|
@ -0,0 +1,185 @@
|
|||
@extends('layouts.user-app')
|
||||
|
||||
@section('page-title', '📋 Hasil Diagnosa')
|
||||
@section('page-subtitle', 'Hasil analisis penyakit tanaman kopi kamu')
|
||||
|
||||
@section('content')
|
||||
|
||||
<div class="grid grid-cols-1 lg:grid-cols-3 gap-6">
|
||||
|
||||
<!-- Hasil Utama -->
|
||||
<div class="lg:col-span-2 space-y-6">
|
||||
|
||||
<!-- Penyakit Final -->
|
||||
<div class="bg-white rounded-2xl shadow-lg p-6">
|
||||
<div class="flex items-center mb-6">
|
||||
<div class="bg-gradient-to-r from-green-500 to-green-600 rounded-xl p-3 mr-4">
|
||||
<svg class="w-6 h-6 text-white" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z"></path>
|
||||
</svg>
|
||||
</div>
|
||||
<h3 class="text-xl font-bold text-gray-800">Hasil Diagnosa</h3>
|
||||
</div>
|
||||
|
||||
@if($riwayat->penyakit)
|
||||
<!-- Penyakit Terdeteksi -->
|
||||
<div class="bg-gradient-to-r from-green-50 to-green-100 border border-green-200 rounded-xl p-5 mb-4">
|
||||
<div class="flex items-start justify-between">
|
||||
<div>
|
||||
<p class="text-xs text-green-600 font-semibold uppercase mb-1">Penyakit Terdeteksi</p>
|
||||
<h2 class="text-2xl font-bold text-green-800">{{ $riwayat->penyakit->nama_penyakit }}</h2>
|
||||
@if($riwayat->penyakit->nama_latin)
|
||||
<p class="text-sm text-green-600 italic mt-1">{{ $riwayat->penyakit->nama_latin }}</p>
|
||||
@endif
|
||||
</div>
|
||||
<div class="text-right">
|
||||
<p class="text-xs text-green-600 font-semibold mb-1">Tingkat Kepercayaan</p>
|
||||
<p class="text-3xl font-bold text-green-700">{{ round($riwayat->cf_tertinggi * 100, 1) }}%</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Progress Bar CF -->
|
||||
<div class="mt-4">
|
||||
<div class="w-full bg-green-200 rounded-full h-3">
|
||||
<div class="bg-green-600 h-3 rounded-full transition-all duration-1000"
|
||||
style="width: {{ round($riwayat->cf_tertinggi * 100, 1) }}%"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Badge tingkat bahaya -->
|
||||
@if($riwayat->penyakit->tingkat_bahaya)
|
||||
<div class="mt-3">
|
||||
<span class="px-3 py-1 text-xs font-bold rounded-full
|
||||
{{ $riwayat->penyakit->tingkat_bahaya === 'Sangat Tinggi' ? 'bg-red-100 text-red-700' :
|
||||
($riwayat->penyakit->tingkat_bahaya === 'Tinggi' ? 'bg-orange-100 text-orange-700' :
|
||||
($riwayat->penyakit->tingkat_bahaya === 'Sedang' ? 'bg-yellow-100 text-yellow-700' : 'bg-green-100 text-green-700')) }}">
|
||||
⚠️ Tingkat Bahaya: {{ $riwayat->penyakit->tingkat_bahaya }}
|
||||
</span>
|
||||
</div>
|
||||
@endif
|
||||
</div>
|
||||
|
||||
<!-- Detail Penyakit -->
|
||||
@if($riwayat->penyakit->deskripsi_singkat)
|
||||
<div class="mb-4">
|
||||
<h4 class="font-bold text-gray-700 mb-2">📝 Deskripsi</h4>
|
||||
<p class="text-sm text-gray-600 leading-relaxed">{{ $riwayat->penyakit->deskripsi_singkat }}</p>
|
||||
</div>
|
||||
@endif
|
||||
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
|
||||
@if($riwayat->penyakit->pengendalian_pencegahan)
|
||||
<div class="bg-blue-50 rounded-xl p-4">
|
||||
<h4 class="font-bold text-blue-700 mb-2 text-sm">🛡️ Pencegahan</h4>
|
||||
<p class="text-xs text-blue-600 leading-relaxed">{{ $riwayat->penyakit->pengendalian_pencegahan }}</p>
|
||||
</div>
|
||||
@endif
|
||||
@if($riwayat->penyakit->pengendalian_kimia)
|
||||
<div class="bg-orange-50 rounded-xl p-4">
|
||||
<h4 class="font-bold text-orange-700 mb-2 text-sm">⚗️ Pengendalian Kimia</h4>
|
||||
<p class="text-xs text-orange-600 leading-relaxed">{{ $riwayat->penyakit->pengendalian_kimia }}</p>
|
||||
</div>
|
||||
@endif
|
||||
@if($riwayat->penyakit->pengendalian_organik)
|
||||
<div class="bg-green-50 rounded-xl p-4">
|
||||
<h4 class="font-bold text-green-700 mb-2 text-sm">🌿 Pengendalian Organik</h4>
|
||||
<p class="text-xs text-green-600 leading-relaxed">{{ $riwayat->penyakit->pengendalian_organik }}</p>
|
||||
</div>
|
||||
@endif
|
||||
@if($riwayat->penyakit->pengendalian_budidaya)
|
||||
<div class="bg-yellow-50 rounded-xl p-4">
|
||||
<h4 class="font-bold text-yellow-700 mb-2 text-sm">🌱 Pengendalian Budidaya</h4>
|
||||
<p class="text-xs text-yellow-600 leading-relaxed">{{ $riwayat->penyakit->pengendalian_budidaya }}</p>
|
||||
</div>
|
||||
@endif
|
||||
</div>
|
||||
@else
|
||||
<div class="text-center py-8 text-gray-400">
|
||||
<p>Tidak ditemukan data penyakit</p>
|
||||
</div>
|
||||
@endif
|
||||
</div>
|
||||
|
||||
<!-- Semua Hasil CF -->
|
||||
@if($riwayat->hasil_diagnosa && count($riwayat->hasil_diagnosa) > 1)
|
||||
<div class="bg-white rounded-2xl shadow-lg p-6">
|
||||
<h3 class="text-lg font-bold text-gray-800 mb-4">📊 Semua Kemungkinan Penyakit</h3>
|
||||
<div class="space-y-3">
|
||||
@foreach($riwayat->hasil_diagnosa as $index => $hasil)
|
||||
<div class="flex items-center justify-between p-3 rounded-xl {{ $index === 0 ? 'bg-green-50 border border-green-200' : 'bg-gray-50' }}">
|
||||
<div class="flex items-center space-x-3">
|
||||
<span class="w-6 h-6 rounded-full {{ $index === 0 ? 'bg-green-500' : 'bg-gray-300' }} text-white text-xs flex items-center justify-center font-bold">
|
||||
{{ $index + 1 }}
|
||||
</span>
|
||||
<span class="text-sm font-semibold {{ $index === 0 ? 'text-green-800' : 'text-gray-700' }}">
|
||||
{{ $hasil['nama_penyakit'] }}
|
||||
</span>
|
||||
</div>
|
||||
<div class="flex items-center space-x-3">
|
||||
<div class="w-24 bg-gray-200 rounded-full h-2">
|
||||
<div class="{{ $index === 0 ? 'bg-green-500' : 'bg-gray-400' }} h-2 rounded-full"
|
||||
style="width: {{ $hasil['persentase'] }}%"></div>
|
||||
</div>
|
||||
<span class="text-sm font-bold {{ $index === 0 ? 'text-green-700' : 'text-gray-600' }}">
|
||||
{{ $hasil['persentase'] }}%
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
@endforeach
|
||||
</div>
|
||||
</div>
|
||||
@endif
|
||||
</div>
|
||||
|
||||
<!-- Panel Kanan -->
|
||||
<div class="space-y-6">
|
||||
|
||||
<!-- Info Diagnosa -->
|
||||
<div class="bg-white rounded-2xl shadow-lg p-6">
|
||||
<h3 class="text-lg font-bold text-gray-800 mb-4">ℹ️ Info Diagnosa</h3>
|
||||
<div class="space-y-3">
|
||||
<div class="flex justify-between text-sm">
|
||||
<span class="text-gray-500">Tanggal</span>
|
||||
<span class="font-semibold text-gray-800">{{ $riwayat->tanggal->format('d M Y, H:i') }}</span>
|
||||
</div>
|
||||
<div class="flex justify-between text-sm">
|
||||
<span class="text-gray-500">Jumlah Gejala</span>
|
||||
<span class="font-semibold text-gray-800">{{ count($riwayat->gejala_input) }} gejala</span>
|
||||
</div>
|
||||
<div class="flex justify-between text-sm">
|
||||
<span class="text-gray-500">CF Tertinggi</span>
|
||||
<span class="font-semibold text-green-600">{{ round($riwayat->cf_tertinggi * 100, 1) }}%</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Gejala yang Dipilih -->
|
||||
<div class="bg-white rounded-2xl shadow-lg p-6">
|
||||
<h3 class="text-lg font-bold text-gray-800 mb-4">🩺 Gejala yang Dipilih</h3>
|
||||
<div class="space-y-2">
|
||||
@foreach($gejalaInput as $gejala)
|
||||
<div class="flex items-center space-x-2 text-sm">
|
||||
<svg class="w-4 h-4 text-green-500 flex-shrink-0" fill="currentColor" viewBox="0 0 20 20">
|
||||
<path fill-rule="evenodd" d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.707-9.293a1 1 0 00-1.414-1.414L9 10.586 7.707 9.293a1 1 0 00-1.414 1.414l2 2a1 1 0 001.414 0l4-4z" clip-rule="evenodd"/>
|
||||
</svg>
|
||||
<span class="text-gray-700">{{ $gejala->nama_gejala }}</span>
|
||||
</div>
|
||||
@endforeach
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Aksi -->
|
||||
<div class="bg-white rounded-2xl shadow-lg p-6 space-y-3">
|
||||
<a href="{{ route('user.diagnosa.index') }}"
|
||||
class="w-full flex items-center justify-center px-4 py-3 bg-gradient-to-r from-green-500 to-green-600 text-white font-bold rounded-xl hover:from-green-600 hover:to-green-700 transition shadow text-sm">
|
||||
🔍 Diagnosa Ulang
|
||||
</a>
|
||||
<a href="{{ route('user.diagnosa.riwayat') }}"
|
||||
class="w-full flex items-center justify-center px-4 py-3 border border-gray-300 text-gray-700 font-semibold rounded-xl hover:bg-gray-50 transition text-sm">
|
||||
📋 Lihat Riwayat
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@endsection
|
||||
|
|
@ -0,0 +1,172 @@
|
|||
@extends('layouts.user-app')
|
||||
|
||||
@section('page-title', '🔍 Diagnosa Penyakit')
|
||||
@section('page-subtitle', 'Pilih gejala yang dialami tanaman kopi kamu')
|
||||
|
||||
@section('content')
|
||||
|
||||
@if(session('error'))
|
||||
<div class="mb-6 bg-red-100 border-l-4 border-red-500 text-red-700 p-4 rounded-lg flex items-center">
|
||||
<svg class="w-6 h-6 mr-3" fill="currentColor" viewBox="0 0 20 20">
|
||||
<path fill-rule="evenodd" d="M10 18a8 8 0 100-16 8 8 0 000 16zM8.707 7.293a1 1 0 00-1.414 1.414L8.586 10l-1.293 1.293a1 1 0 101.414 1.414L10 11.414l1.293 1.293a1 1 0 001.414-1.414L11.414 10l1.293-1.293a1 1 0 00-1.414-1.414L10 8.586 8.707 7.293z" clip-rule="evenodd"/>
|
||||
</svg>
|
||||
<span class="font-semibold">{{ session('error') }}</span>
|
||||
</div>
|
||||
@endif
|
||||
|
||||
<form action="{{ route('user.diagnosa.proses') }}" method="POST" id="form-diagnosa">
|
||||
@csrf
|
||||
|
||||
<div class="grid grid-cols-1 lg:grid-cols-3 gap-6">
|
||||
|
||||
<!-- Daftar Gejala -->
|
||||
<div class="lg:col-span-2">
|
||||
<div class="bg-white rounded-2xl shadow-lg p-6">
|
||||
<div class="flex items-center justify-between mb-6">
|
||||
<div class="flex items-center">
|
||||
<div class="bg-gradient-to-r from-green-500 to-green-600 rounded-xl p-3 mr-4">
|
||||
<svg class="w-6 h-6 text-white" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path>
|
||||
</svg>
|
||||
</div>
|
||||
<div>
|
||||
<h3 class="text-lg font-bold text-gray-800">Pilih Gejala</h3>
|
||||
<p class="text-sm text-gray-500">Centang gejala yang sesuai dengan kondisi tanaman</p>
|
||||
</div>
|
||||
</div>
|
||||
<!-- Search -->
|
||||
<input type="text" id="search-gejala" placeholder="🔍 Cari gejala..."
|
||||
class="px-4 py-2 border border-gray-300 rounded-xl text-sm focus:ring-2 focus:ring-green-500 focus:border-transparent w-48">
|
||||
</div>
|
||||
|
||||
<!-- Gejala List -->
|
||||
<div class="space-y-3 max-h-[500px] overflow-y-auto pr-2" id="gejala-list">
|
||||
@foreach($gejalas as $index => $gejala)
|
||||
<label for="gejala_{{ $gejala->id_gejala }}"
|
||||
class="gejala-item flex items-center p-4 border-2 border-gray-200 rounded-xl cursor-pointer hover:border-green-400 hover:bg-green-50 transition-all group"
|
||||
data-nama="{{ strtolower($gejala->nama_gejala) }}">
|
||||
<input type="checkbox" name="gejala[]" value="{{ $gejala->id_gejala }}"
|
||||
id="gejala_{{ $gejala->id_gejala }}"
|
||||
class="gejala-checkbox w-5 h-5 text-green-600 rounded focus:ring-green-500 mr-4"
|
||||
onchange="updateSelected()">
|
||||
<div class="flex-1">
|
||||
<span class="text-sm font-semibold text-gray-700 group-hover:text-green-700">
|
||||
{{ $gejala->nama_gejala }}
|
||||
</span>
|
||||
</div>
|
||||
<div class="w-6 h-6 rounded-full border-2 border-gray-300 group-hover:border-green-400 flex items-center justify-center checkmark hidden">
|
||||
<svg class="w-4 h-4 text-green-600" fill="currentColor" viewBox="0 0 20 20">
|
||||
<path fill-rule="evenodd" d="M16.707 5.293a1 1 0 010 1.414l-8 8a1 1 0 01-1.414 0l-4-4a1 1 0 011.414-1.414L8 12.586l7.293-7.293a1 1 0 011.414 0z" clip-rule="evenodd"/>
|
||||
</svg>
|
||||
</div>
|
||||
</label>
|
||||
@endforeach
|
||||
</div>
|
||||
|
||||
@error('gejala')
|
||||
<p class="text-red-500 text-sm mt-3">{{ $message }}</p>
|
||||
@enderror
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Panel Kanan -->
|
||||
<div class="space-y-6">
|
||||
|
||||
<!-- Gejala Terpilih -->
|
||||
<div class="bg-white rounded-2xl shadow-lg p-6 sticky top-28">
|
||||
<h3 class="text-lg font-bold text-gray-800 mb-4">✅ Gejala Terpilih</h3>
|
||||
|
||||
<div id="selected-count" class="text-3xl font-bold text-green-600 mb-1">0</div>
|
||||
<p class="text-sm text-gray-500 mb-4">gejala dipilih</p>
|
||||
|
||||
<div id="selected-list" class="space-y-2 max-h-64 overflow-y-auto mb-6">
|
||||
<p class="text-sm text-gray-400 italic" id="empty-msg">Belum ada gejala dipilih</p>
|
||||
</div>
|
||||
|
||||
<button type="button" onclick="resetGejala()"
|
||||
class="w-full mb-3 px-4 py-2 border border-gray-300 text-gray-600 font-semibold rounded-xl hover:bg-gray-50 transition text-sm">
|
||||
Reset Pilihan
|
||||
</button>
|
||||
|
||||
<button type="submit"
|
||||
class="w-full px-4 py-3 bg-gradient-to-r from-green-500 to-green-600 text-white font-bold rounded-xl hover:from-green-600 hover:to-green-700 transition shadow-lg text-sm">
|
||||
🔍 Diagnosa Sekarang
|
||||
</button>
|
||||
|
||||
<!-- Info -->
|
||||
<div class="mt-4 p-3 bg-green-50 rounded-xl">
|
||||
<p class="text-xs text-green-700">
|
||||
💡 Pilih semua gejala yang kamu amati pada tanaman untuk hasil diagnosa yang lebih akurat.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
@endsection
|
||||
|
||||
@push('scripts')
|
||||
<script>
|
||||
const gejalaData = {};
|
||||
|
||||
function updateSelected() {
|
||||
const checkboxes = document.querySelectorAll('.gejala-checkbox:checked');
|
||||
const count = checkboxes.length;
|
||||
document.getElementById('selected-count').textContent = count;
|
||||
|
||||
const list = document.getElementById('selected-list');
|
||||
const emptyMsg = document.getElementById('empty-msg');
|
||||
|
||||
if (count === 0) {
|
||||
list.innerHTML = '<p class="text-sm text-gray-400 italic" id="empty-msg">Belum ada gejala dipilih</p>';
|
||||
return;
|
||||
}
|
||||
|
||||
list.innerHTML = '';
|
||||
checkboxes.forEach(cb => {
|
||||
const label = document.querySelector(`label[for="${cb.id}"] .flex-1 span`);
|
||||
const nama = label ? label.textContent.trim() : cb.value;
|
||||
list.innerHTML += `
|
||||
<div class="flex items-center justify-between bg-green-50 px-3 py-2 rounded-lg">
|
||||
<span class="text-xs font-medium text-green-800">${nama}</span>
|
||||
<button type="button" onclick="removeGejala('${cb.id}')" class="text-green-500 hover:text-red-500 ml-2">✕</button>
|
||||
</div>`;
|
||||
});
|
||||
|
||||
// Update label styling
|
||||
document.querySelectorAll('.gejala-item').forEach(label => {
|
||||
const cb = label.querySelector('.gejala-checkbox');
|
||||
if (cb.checked) {
|
||||
label.classList.add('border-green-500', 'bg-green-50');
|
||||
label.classList.remove('border-gray-200');
|
||||
} else {
|
||||
label.classList.remove('border-green-500', 'bg-green-50');
|
||||
label.classList.add('border-gray-200');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function removeGejala(id) {
|
||||
const cb = document.getElementById(id);
|
||||
if (cb) {
|
||||
cb.checked = false;
|
||||
updateSelected();
|
||||
}
|
||||
}
|
||||
|
||||
function resetGejala() {
|
||||
document.querySelectorAll('.gejala-checkbox').forEach(cb => cb.checked = false);
|
||||
updateSelected();
|
||||
}
|
||||
|
||||
// Search gejala
|
||||
document.getElementById('search-gejala').addEventListener('input', function() {
|
||||
const keyword = this.value.toLowerCase();
|
||||
document.querySelectorAll('.gejala-item').forEach(item => {
|
||||
const nama = item.getAttribute('data-nama');
|
||||
item.style.display = nama.includes(keyword) ? '' : 'none';
|
||||
});
|
||||
});
|
||||
</script>
|
||||
@endpush
|
||||
|
|
@ -0,0 +1,87 @@
|
|||
@extends('layouts.user-app')
|
||||
|
||||
@section('page-title', '📋 Riwayat Diagnosa')
|
||||
@section('page-subtitle', 'Histori diagnosa penyakit tanaman kopi kamu')
|
||||
|
||||
@section('content')
|
||||
|
||||
<div class="bg-white rounded-2xl shadow-lg">
|
||||
<div class="p-8">
|
||||
<div class="flex items-center justify-between mb-6">
|
||||
<div class="flex items-center">
|
||||
<div class="bg-gradient-to-r from-green-500 to-green-600 rounded-xl p-3 mr-4">
|
||||
<svg class="w-6 h-6 text-white" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 8v4l3 3m6-3a9 9 0 11-18 0 9 9 0 0118 0z"></path>
|
||||
</svg>
|
||||
</div>
|
||||
<h3 class="text-xl font-bold text-gray-800">Riwayat Diagnosa</h3>
|
||||
</div>
|
||||
<a href="{{ route('user.diagnosa.index') }}"
|
||||
class="flex items-center px-5 py-3 bg-gradient-to-r from-green-500 to-green-600 text-white font-bold rounded-xl hover:from-green-600 hover:to-green-700 transition shadow-lg text-sm">
|
||||
+ Diagnosa Baru
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div class="overflow-x-auto rounded-xl border border-gray-200">
|
||||
<table class="min-w-full divide-y divide-gray-200">
|
||||
<thead class="bg-gray-50">
|
||||
<tr>
|
||||
<th class="px-6 py-4 text-left text-xs font-bold text-gray-600 uppercase">No</th>
|
||||
<th class="px-6 py-4 text-left text-xs font-bold text-gray-600 uppercase">Tanggal</th>
|
||||
<th class="px-6 py-4 text-left text-xs font-bold text-gray-600 uppercase">Penyakit</th>
|
||||
<th class="px-6 py-4 text-left text-xs font-bold text-gray-600 uppercase">Gejala</th>
|
||||
<th class="px-6 py-4 text-left text-xs font-bold text-gray-600 uppercase">CF</th>
|
||||
<th class="px-6 py-4 text-center text-xs font-bold text-gray-600 uppercase">Aksi</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody class="bg-white divide-y divide-gray-200">
|
||||
@forelse($riwayats as $index => $riwayat)
|
||||
<tr class="hover:bg-gray-50 transition-colors">
|
||||
<td class="px-6 py-4 text-sm">{{ $riwayats->firstItem() + $index }}</td>
|
||||
<td class="px-6 py-4 text-sm text-gray-600">{{ $riwayat->tanggal->format('d M Y, H:i') }}</td>
|
||||
<td class="px-6 py-4">
|
||||
<span class="text-sm font-semibold text-gray-800">
|
||||
{{ $riwayat->penyakit->nama_penyakit ?? '-' }}
|
||||
</span>
|
||||
</td>
|
||||
<td class="px-6 py-4">
|
||||
<span class="px-2 py-1 text-xs font-bold rounded-full bg-blue-100 text-blue-700">
|
||||
{{ count($riwayat->gejala_input) }} gejala
|
||||
</span>
|
||||
</td>
|
||||
<td class="px-6 py-4">
|
||||
<span class="px-2 py-1 text-xs font-bold rounded-full
|
||||
{{ $riwayat->cf_tertinggi >= 0.8 ? 'bg-red-100 text-red-700' :
|
||||
($riwayat->cf_tertinggi >= 0.5 ? 'bg-yellow-100 text-yellow-700' : 'bg-green-100 text-green-700') }}">
|
||||
{{ round($riwayat->cf_tertinggi * 100, 1) }}%
|
||||
</span>
|
||||
</td>
|
||||
<td class="px-6 py-4 text-center">
|
||||
<a href="{{ route('user.diagnosa.hasil', $riwayat->id_diagnosis) }}"
|
||||
class="inline-flex items-center px-3 py-2 bg-green-500 text-white text-xs font-semibold rounded-lg hover:bg-green-600 transition">
|
||||
Lihat Detail
|
||||
</a>
|
||||
</td>
|
||||
</tr>
|
||||
@empty
|
||||
<tr>
|
||||
<td colspan="6" class="px-6 py-12 text-center text-gray-400">
|
||||
<svg class="w-16 h-16 mx-auto mb-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path>
|
||||
</svg>
|
||||
<p class="text-xl font-semibold mb-2">Belum ada riwayat diagnosa</p>
|
||||
<a href="{{ route('user.diagnosa.index') }}" class="text-green-600 font-semibold hover:underline">
|
||||
Mulai diagnosa sekarang
|
||||
</a>
|
||||
</td>
|
||||
</tr>
|
||||
@endforelse
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<div class="mt-6">{{ $riwayats->links() }}</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@endsection
|
||||
|
|
@ -9,12 +9,14 @@
|
|||
use App\Http\Controllers\Admin\RuleBasisController;
|
||||
use App\Http\Controllers\Admin\ArtikelBudidayaController;
|
||||
use App\Http\Controllers\Admin\ArtikelHamaPenyakitController;
|
||||
use App\Http\Controllers\User\UserDashboardController;
|
||||
use App\Http\Controllers\User\DiagnosaController;
|
||||
use App\Http\Controllers\User\ArtikelUserController;
|
||||
|
||||
Route::get('/', function () {
|
||||
return view('welcome');
|
||||
});
|
||||
|
||||
// Dashboard untuk user biasa
|
||||
//LOGIN
|
||||
Route::middleware('auth')->group(function () {
|
||||
Route::get('/dashboard', function () {
|
||||
// Redirect berdasarkan role
|
||||
|
|
@ -23,9 +25,24 @@
|
|||
} elseif (auth()->user()->role === 'admin') {
|
||||
return redirect()->route('admin.dashboard');
|
||||
}
|
||||
return view('dashboard');
|
||||
return redirect()->route('user.dashboard');
|
||||
})->name('dashboard');
|
||||
});
|
||||
//USER
|
||||
Route::middleware(['auth', App\Http\Middleware\IsUser::class])
|
||||
->prefix('user')
|
||||
->name('user.')
|
||||
->group(function () {
|
||||
Route::get('/dashboard', [UserDashboardController::class, 'index'])->name('dashboard');
|
||||
Route::get('/diagnosa', [DiagnosaController::class, 'index'])->name('diagnosa.index');
|
||||
Route::post('/diagnosa', [DiagnosaController::class, 'proses'])->name('diagnosa.proses');
|
||||
Route::get('/diagnosa/hasil/{id}', [DiagnosaController::class, 'hasil'])->name('diagnosa.hasil');
|
||||
Route::get('/diagnosa/riwayat', [DiagnosaController::class, 'riwayat'])->name('diagnosa.riwayat');
|
||||
Route::get('/artikel/budidaya', [ArtikelUserController::class, 'budidaya'])->name('artikel.budidaya');
|
||||
Route::get('/artikel/budidaya/{slug}', [ArtikelUserController::class, 'detailBudidaya'])->name('artikel.budidaya.detail');
|
||||
Route::get('/artikel/hama-penyakit', [ArtikelUserController::class, 'hamaPenyakit'])->name('artikel.hama-penyakit');
|
||||
Route::get('/artikel/hama-penyakit/{slug}', [ArtikelUserController::class, 'detailHamaPenyakit'])->name('artikel.hama-penyakit.detail');
|
||||
});
|
||||
|
||||
// Super Admin Routes
|
||||
Route::middleware(['auth', App\Http\Middleware\IsSuperAdmin::class])->prefix('super-admin')->name('super-admin.')->group(function () {
|
||||
|
|
@ -36,7 +53,7 @@
|
|||
Route::resource('users', App\Http\Controllers\SuperAdmin\UserManagementController::class);
|
||||
});
|
||||
|
||||
// Admin Routes (kalau ada)
|
||||
// Admin Routes
|
||||
Route::middleware(['auth', App\Http\Middleware\IsAdmin::class])
|
||||
->prefix('admin')
|
||||
->name('admin.')
|
||||
|
|
|
|||
Loading…
Reference in New Issue