user:dashboard done

This commit is contained in:
E31232303evimr 2026-03-03 19:08:21 +07:00
parent 1c8fd53f16
commit 23b28a1590
18 changed files with 1206 additions and 60 deletions

View File

@ -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'));
}
}

View File

@ -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'));
}
}

View File

@ -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'
));
}
}

View File

@ -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.');
}
}

View File

@ -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 {

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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'))

View File

@ -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>

View File

@ -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">
&copy; {{ date('Y') }} Coffee Expert System. All rights reserved.
</div>
</footer>
</div>
</div>
@stack('scripts')
</body>
</html>

View File

@ -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')

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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.')