RESPONSIFFF
This commit is contained in:
parent
2d24152cc0
commit
2ad9c6f295
|
|
@ -0,0 +1,10 @@
|
|||
<?php
|
||||
define('LARAVEL_START', microtime(true));
|
||||
require __DIR__.'/vendor/autoload.php';
|
||||
$app = require_once __DIR__.'/bootstrap/app.php';
|
||||
$kernel = $app->make(Illuminate\Contracts\Console\Kernel::class);
|
||||
$kernel->call('config:clear');
|
||||
$kernel->call('cache:clear');
|
||||
$kernel->call('view:clear');
|
||||
$kernel->call('route:clear');
|
||||
echo "Cache cleared!";
|
||||
|
|
@ -1,5 +1,6 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}" x-data="{ sidebarOpen: true }" x-cloak>
|
||||
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}"
|
||||
x-data="{ sidebarOpen: true, mobileOpen: false }">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
|
|
@ -8,97 +9,77 @@
|
|||
<title>{{ config('app.name') }} | @yield('page-title', 'Dashboard')</title>
|
||||
<link rel="icon" href="{{ asset('asset/images/v2_nobg.png') }}?v=2" type="image/png">
|
||||
|
||||
<!-- Fonts -->
|
||||
<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" />
|
||||
|
||||
<!-- Scripts -->
|
||||
@vite(['resources/css/app.css', 'resources/js/app.js'])
|
||||
|
||||
<!-- Alpine.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; }
|
||||
|
||||
* {
|
||||
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; }
|
||||
|
||||
/* Custom Scrollbar */
|
||||
::-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 */
|
||||
.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);
|
||||
transition: width 0.3s cubic-bezier(0.4,0,0.2,1),
|
||||
margin-left 0.3s cubic-bezier(0.4,0,0.2,1),
|
||||
left 0.3s cubic-bezier(0.4,0,0.2,1);
|
||||
}
|
||||
.sidebar-overlay {
|
||||
position: fixed; inset: 0; background: rgba(0,0,0,.5); z-index: 25;
|
||||
}
|
||||
|
||||
/* Logo Float Animation */
|
||||
@keyframes float {
|
||||
0%, 100% { transform: translateY(0px); }
|
||||
0%,100% { transform: translateY(0px); }
|
||||
50% { transform: translateY(-5px); }
|
||||
}
|
||||
.logo-float { animation: float 3s ease-in-out infinite; }
|
||||
|
||||
.logo-float {
|
||||
animation: float 3s ease-in-out infinite;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Page Fade In Animation */
|
||||
@keyframes fadeInUp {
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: translateY(20px);
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: translateY(0);
|
||||
}
|
||||
from { opacity:0; transform:translateY(20px); }
|
||||
to { opacity:1; transform:translateY(0); }
|
||||
}
|
||||
.page-content { animation: fadeInUp .5s ease-out; }
|
||||
|
||||
.page-content {
|
||||
animation: fadeInUp 0.5s ease-out;
|
||||
}
|
||||
|
||||
/* Badge Pulse */
|
||||
@keyframes pulse {
|
||||
0%, 100% { opacity: 1; }
|
||||
50% { opacity: 0.5; }
|
||||
0%,100% { opacity:1; }
|
||||
50% { opacity:.5; }
|
||||
}
|
||||
.badge-pulse { animation: pulse 2s cubic-bezier(.4,0,.6,1) infinite; }
|
||||
@media (max-width: 1023px) {
|
||||
.sidebar-desktop { display: none !important; }
|
||||
.main-content { margin-left: 0 !important; }
|
||||
.header-bar { left: 0 !important; }
|
||||
}
|
||||
|
||||
.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">
|
||||
<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 Section -->
|
||||
{{-- ── Mobile overlay ── --}}
|
||||
<div x-show="mobileOpen"
|
||||
x-transition:enter="transition ease-out duration-200"
|
||||
x-transition:enter-start="opacity-0"
|
||||
x-transition:enter-end="opacity-100"
|
||||
x-transition:leave="transition ease-in duration-200"
|
||||
x-transition:leave-start="opacity-100"
|
||||
x-transition:leave-end="opacity-0"
|
||||
class="sidebar-overlay lg:hidden"
|
||||
@click="mobileOpen = false">
|
||||
</div>
|
||||
|
||||
{{-- ── Sidebar Desktop (collapse/expand) ── --}}
|
||||
<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-col shadow-2xl sidebar-desktop" style="display:flex;">
|
||||
|
||||
<!-- 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">
|
||||
|
|
@ -109,159 +90,262 @@ class="sidebar-transition bg-gradient-to-b from-gray-900 via-gray-800 to-gray-90
|
|||
</div>
|
||||
<div>
|
||||
<h1 class="text-lg font-bold bg-gradient-to-r from-green-400 to-green-200 bg-clip-text text-transparent">Cek Kopi</h1>
|
||||
<p class="text-xs text-gray-400">Admin</p>
|
||||
</div>
|
||||
</div>
|
||||
<button
|
||||
@click="sidebarOpen = !sidebarOpen"
|
||||
class="p-2 rounded-lg hover:bg-gray-700 transition-colors"
|
||||
>
|
||||
<div x-show="!sidebarOpen" class="mx-auto logo-float">
|
||||
<div class="w-10 h-10 rounded-xl overflow-hidden shadow-lg">
|
||||
<img src="{{ asset('asset/images/ori_nobg.png') }}" class="w-full h-full object-cover" alt="Logo">
|
||||
</div>
|
||||
</div>
|
||||
<button @click="sidebarOpen = !sidebarOpen"
|
||||
class="p-2 rounded-lg hover:bg-gray-700 transition-colors flex-shrink-0">
|
||||
<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>
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 6h16M4 12h16M4 18h16"/>
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Navigation Menu -->
|
||||
<!-- Nav Desktop -->
|
||||
<nav class="flex-1 px-4 py-6 space-y-2 overflow-y-auto">
|
||||
<!-- Dashboard -->
|
||||
|
||||
<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">
|
||||
class="flex items-center px-4 py-3 rounded-xl hover:bg-gray-700 {{ request()->routeIs('admin.dashboard') ? 'bg-gray-700' : '' }} group">
|
||||
<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 flex-shrink-0">
|
||||
<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>
|
||||
<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"/>
|
||||
</svg>
|
||||
</div>
|
||||
<span x-show="sidebarOpen" class="ml-3 font-semibold">Dashboard</span>
|
||||
</div>
|
||||
</a>
|
||||
|
||||
<!-- Penyakit Management -->
|
||||
<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">
|
||||
class="flex items-center px-4 py-3 rounded-xl hover:bg-gray-700 {{ request()->routeIs('admin.penyakit.*') ? 'bg-gray-700' : '' }} group">
|
||||
<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 flex-shrink-0">
|
||||
<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="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>
|
||||
<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"/>
|
||||
</svg>
|
||||
</div>
|
||||
<span x-show="sidebarOpen" class="ml-3 font-semibold">Penyakit</span>
|
||||
</div>
|
||||
</a>
|
||||
|
||||
<!-- Gejala Management -->
|
||||
<a href="{{ route('admin.gejala.index') }}"
|
||||
class="menu-item flex items-center px-4 py-3 rounded-xl hover:bg-gray-700 {{ request()->routeIs('admin.gejala.*') ? '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-green-500/20 group-hover:bg-green-500/30 transition-colors">
|
||||
class="flex items-center px-4 py-3 rounded-xl hover:bg-gray-700 {{ request()->routeIs('admin.gejala.*') ? 'bg-gray-700' : '' }} group">
|
||||
<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 flex-shrink-0">
|
||||
<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>
|
||||
<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"/>
|
||||
</svg>
|
||||
</div>
|
||||
<span x-show="sidebarOpen" class="ml-3 font-semibold">Gejala</span>
|
||||
</div>
|
||||
</a>
|
||||
|
||||
<!-- Rule Basis Management -->
|
||||
<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 group-hover:bg-blue-500/30 transition-colors" style="background-color: rgba(139, 92, 246, 0.2);">
|
||||
<svg class="w-5 h-5" style="color: #a78bfa;" 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>
|
||||
class="flex items-center px-4 py-3 rounded-xl hover:bg-gray-700 {{ request()->routeIs('admin.rule-basis.*') ? 'bg-gray-700' : '' }} group">
|
||||
<div class="w-10 h-10 flex items-center justify-center rounded-lg transition-colors flex-shrink-0" style="background:rgba(139,92,246,.2);">
|
||||
<svg class="w-5 h-5" style="color:#a78bfa;" 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"/>
|
||||
</svg>
|
||||
</div>
|
||||
<span x-show="sidebarOpen" class="ml-3 font-semibold">Rule Basis</span>
|
||||
</div>
|
||||
</a>
|
||||
|
||||
<!-- Informasi Management (Dropdown) -->
|
||||
<div x-data="{ informasiOpen: {{ request()->routeIs('admin.artikel-budidaya.*') || request()->routeIs('admin.artikel-hama-penyakit.*') ? 'true' : 'false' }} }">
|
||||
|
||||
<!-- Dropdown Toggle -->
|
||||
<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">
|
||||
<!-- Artikel dropdown -->
|
||||
<div x-data="{ open: {{ request()->routeIs('admin.artikel-budidaya.*') || request()->routeIs('admin.artikel-hama-penyakit.*') ? 'true' : 'false' }} }">
|
||||
<button @click="open = !open"
|
||||
class="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.*') ? 'bg-gray-700' : '' }} group">
|
||||
<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 flex-shrink-0">
|
||||
<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>
|
||||
<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"/>
|
||||
</svg>
|
||||
</div>
|
||||
<span x-show="sidebarOpen" class="ml-3 font-semibold">Artikel</span>
|
||||
</div>
|
||||
<svg x-show="sidebarOpen" :class="informasiOpen ? 'rotate-180' : ''"
|
||||
<span x-show="sidebarOpen" class="ml-3 font-semibold flex-1 text-left">Artikel</span>
|
||||
<svg x-show="sidebarOpen" :class="open ? '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>
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7"/>
|
||||
</svg>
|
||||
</button>
|
||||
|
||||
<!-- Sub Menu -->
|
||||
<div x-show="informasiOpen && sidebarOpen"
|
||||
<div x-show="open && 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">
|
||||
|
||||
<!-- Budidaya -->
|
||||
<a href="{{ route('admin.artikel-budidaya.index') }}"
|
||||
class="flex items-center px-3 py-2 rounded-lg hover:bg-gray-700 {{ request()->routeIs('admin.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>
|
||||
class="flex items-center px-3 py-2 rounded-lg hover:bg-gray-700 {{ request()->routeIs('admin.artikel-budidaya.*') ? 'bg-gray-700 text-white' : 'text-gray-400' }} transition-colors">
|
||||
<span class="text-sm font-medium hover:text-white">Budidaya</span>
|
||||
</a>
|
||||
|
||||
<!-- Hama & Penyakit -->
|
||||
<a href="{{ route('admin.artikel-hama-penyakit.index') }}"
|
||||
class="flex items-center px-3 py-2 rounded-lg hover:bg-gray-700 {{ request()->routeIs('admin.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>
|
||||
class="flex items-center px-3 py-2 rounded-lg hover:bg-gray-700 {{ request()->routeIs('admin.artikel-hama-penyakit.*') ? 'bg-gray-700 text-white' : 'text-gray-400' }} transition-colors">
|
||||
<span class="text-sm font-medium hover:text-white">Hama & Penyakit</span>
|
||||
</a>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</nav>
|
||||
|
||||
<!-- Logout Button -->
|
||||
<!-- Logout Desktop -->
|
||||
<div class="p-4 border-t border-gray-700">
|
||||
<form method="POST" action="{{ route('logout') }}">
|
||||
@csrf
|
||||
<button type="submit" class="menu-item 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">
|
||||
<button type="submit" class="w-full flex items-center px-4 py-3 rounded-xl hover:bg-red-600/20 group">
|
||||
<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 flex-shrink-0">
|
||||
<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>
|
||||
<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"/>
|
||||
</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">
|
||||
{{-- ── Sidebar Mobile Drawer ── --}}
|
||||
<aside x-show="mobileOpen"
|
||||
x-transition:enter="transition ease-out duration-300"
|
||||
x-transition:enter-start="-translate-x-full"
|
||||
x-transition:enter-end="translate-x-0"
|
||||
x-transition:leave="transition ease-in duration-200"
|
||||
x-transition:leave-start="translate-x-0"
|
||||
x-transition:leave-end="-translate-x-full"
|
||||
class="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 w-72 lg:hidden">
|
||||
|
||||
<!-- Top Header - Fixed at top -->
|
||||
<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">
|
||||
<!-- Logo Mobile -->
|
||||
<div class="p-6 border-b border-gray-700">
|
||||
<div class="flex items-center justify-between">
|
||||
<!-- Page Title -->
|
||||
<div class="flex items-center space-x-3">
|
||||
<div class="logo-float">
|
||||
<div class="w-10 h-10 rounded-xl overflow-hidden shadow-lg flex-shrink-0">
|
||||
<img src="{{ asset('asset/images/ori_nobg.png') }}" class="w-full h-full object-cover" alt="Logo">
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<h2 class="text-2xl font-bold text-gray-800">
|
||||
@yield('page-title', 'Dashboard')
|
||||
</h2>
|
||||
<h1 class="text-lg font-bold bg-gradient-to-r from-green-400 to-green-200 bg-clip-text text-transparent">Cek Kopi</h1>
|
||||
<p class="text-xs text-gray-400">Admin</p>
|
||||
</div>
|
||||
</div>
|
||||
<button @click="mobileOpen = false" 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="M6 18L18 6M6 6l12 12"/>
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- User Info -->
|
||||
<div class="flex items-center space-x-4">
|
||||
<!-- Nav Mobile -->
|
||||
<nav class="flex-1 px-4 py-6 space-y-2 overflow-y-auto">
|
||||
|
||||
<!-- User Profile - Clickable -->
|
||||
<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">
|
||||
<a href="{{ route('admin.dashboard') }}" @click="mobileOpen=false"
|
||||
class="flex items-center px-4 py-3 rounded-xl hover:bg-gray-700 {{ request()->routeIs('admin.dashboard') ? 'bg-gray-700' : '' }} group">
|
||||
<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"/>
|
||||
</svg>
|
||||
</div>
|
||||
<span class="ml-3 font-semibold">Dashboard</span>
|
||||
</a>
|
||||
|
||||
<a href="{{ route('admin.penyakit.index') }}" @click="mobileOpen=false"
|
||||
class="flex items-center px-4 py-3 rounded-xl hover:bg-gray-700 {{ request()->routeIs('admin.penyakit.*') ? 'bg-gray-700' : '' }} group">
|
||||
<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="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"/>
|
||||
</svg>
|
||||
</div>
|
||||
<span class="ml-3 font-semibold">Penyakit</span>
|
||||
</a>
|
||||
|
||||
<a href="{{ route('admin.gejala.index') }}" @click="mobileOpen=false"
|
||||
class="flex items-center px-4 py-3 rounded-xl hover:bg-gray-700 {{ request()->routeIs('admin.gejala.*') ? 'bg-gray-700' : '' }} group">
|
||||
<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"/>
|
||||
</svg>
|
||||
</div>
|
||||
<span class="ml-3 font-semibold">Gejala</span>
|
||||
</a>
|
||||
|
||||
<a href="{{ route('admin.rule-basis.index') }}" @click="mobileOpen=false"
|
||||
class="flex items-center px-4 py-3 rounded-xl hover:bg-gray-700 {{ request()->routeIs('admin.rule-basis.*') ? 'bg-gray-700' : '' }} group">
|
||||
<div class="w-10 h-10 flex items-center justify-center rounded-lg transition-colors" style="background:rgba(139,92,246,.2);">
|
||||
<svg class="w-5 h-5" style="color:#a78bfa;" 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"/>
|
||||
</svg>
|
||||
</div>
|
||||
<span class="ml-3 font-semibold">Rule Basis</span>
|
||||
</a>
|
||||
|
||||
<!-- Artikel dropdown mobile -->
|
||||
<div x-data="{ open: {{ request()->routeIs('admin.artikel-budidaya.*') || request()->routeIs('admin.artikel-hama-penyakit.*') ? 'true' : 'false' }} }">
|
||||
<button @click="open = !open"
|
||||
class="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.*') ? 'bg-gray-700' : '' }} group">
|
||||
<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"/>
|
||||
</svg>
|
||||
</div>
|
||||
<span class="ml-3 font-semibold flex-1 text-left">Artikel</span>
|
||||
<svg :class="open ? '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"/>
|
||||
</svg>
|
||||
</button>
|
||||
<div x-show="open" class="mt-1 ml-6 pl-4 border-l-2 border-gray-600 space-y-1">
|
||||
<a href="{{ route('admin.artikel-budidaya.index') }}" @click="mobileOpen=false"
|
||||
class="flex items-center px-3 py-2 rounded-lg hover:bg-gray-700 {{ request()->routeIs('admin.artikel-budidaya.*') ? 'bg-gray-700 text-white' : 'text-gray-400' }} transition-colors">
|
||||
<span class="text-sm font-medium hover:text-white">Budidaya</span>
|
||||
</a>
|
||||
<a href="{{ route('admin.artikel-hama-penyakit.index') }}" @click="mobileOpen=false"
|
||||
class="flex items-center px-3 py-2 rounded-lg hover:bg-gray-700 {{ request()->routeIs('admin.artikel-hama-penyakit.*') ? 'bg-gray-700 text-white' : 'text-gray-400' }} transition-colors">
|
||||
<span class="text-sm font-medium hover:text-white">Hama & Penyakit</span>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</nav>
|
||||
|
||||
<!-- Logout Mobile -->
|
||||
<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="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"/>
|
||||
</svg>
|
||||
</div>
|
||||
<span class="ml-3 font-semibold text-red-400">Logout</span>
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
</aside>
|
||||
|
||||
{{-- ── Main Content ── --}}
|
||||
<div
|
||||
class="flex-1 sidebar-transition main-content" style="margin-left:16rem;">
|
||||
|
||||
<!-- Header -->
|
||||
<header class="bg-white border-b border-gray-200 fixed top-0 right-0 z-20 shadow-sm header-bar" style="left:16rem;"
|
||||
style="transition: left 0.3s cubic-bezier(0.4,0,0.2,1);">
|
||||
<div class="px-4 lg:px-8 py-4">
|
||||
<div class="flex items-center justify-between">
|
||||
<div class="flex items-center gap-3">
|
||||
<!-- Hamburger mobile -->
|
||||
<button @click="mobileOpen = true"
|
||||
class="lg:hidden p-2 rounded-lg hover:bg-gray-100 transition-colors">
|
||||
<svg class="w-6 h-6 text-gray-700" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 6h16M4 12h16M4 18h16"/>
|
||||
</svg>
|
||||
</button>
|
||||
<h2 class="text-xl lg:text-2xl font-bold text-gray-800">@yield('page-title', 'Dashboard')</h2>
|
||||
</div>
|
||||
<div class="flex items-center space-x-4">
|
||||
<a href="{{ route('profile.edit') }}"
|
||||
class="flex items-center space-x-2 lg:space-x-3 px-2 lg: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-8 h-8 lg:w-10 lg: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 text-sm">
|
||||
{{ substr(Auth::user()->nama, 0, 1) }}
|
||||
</div>
|
||||
<div class="text-left">
|
||||
<div class="text-left hidden sm:block">
|
||||
<p class="text-sm font-bold text-gray-800">{{ Auth::user()->nama }}</p>
|
||||
<p class="text-xs text-green-600 font-semibold uppercase">Admin</p>
|
||||
</div>
|
||||
|
|
@ -271,22 +355,22 @@ class="flex items-center px-3 py-2 rounded-lg hover:bg-gray-700 {{ request()->ro
|
|||
</div>
|
||||
</header>
|
||||
|
||||
<!-- Page Content - Scrollable with top padding for fixed header -->
|
||||
<main class="pt-28">
|
||||
<div class="p-8 page-content">
|
||||
<!-- Page Content -->
|
||||
<main style="padding-top: 73px;">
|
||||
<div class="p-4 lg:p-8 page-content">
|
||||
@yield('content')
|
||||
</div>
|
||||
</main>
|
||||
|
||||
<!-- Footer -->
|
||||
<footer class="px-8 py-6 bg-white border-t border-gray-200">
|
||||
<footer class="px-4 lg:px-8 py-6 bg-white border-t border-gray-200">
|
||||
<div class="text-center text-sm text-gray-600">
|
||||
© {{ date('Y') }} Cek Kopi by Evi. All rights reserved.
|
||||
</div>
|
||||
</footer>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@stack('scripts')
|
||||
</div>
|
||||
@stack('scripts')
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}" x-data="{ sidebarOpen: true }" x-cloak>
|
||||
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}" x-data="{ sidebarOpen: true, mobileOpen: false }">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
|
|
@ -16,7 +16,6 @@
|
|||
<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; }
|
||||
|
|
@ -25,7 +24,10 @@
|
|||
::-webkit-scrollbar-thumb:hover { background: #15803d; }
|
||||
|
||||
.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);
|
||||
transition: width 0.3s cubic-bezier(0.4, 0, 0.2, 1), margin-left 0.3s cubic-bezier(0.4, 0, 0.2, 1), transform 0.3s cubic-bezier(0.4, 0, 0.2, 1);
|
||||
}
|
||||
.sidebar-overlay {
|
||||
position: fixed; inset: 0; background: rgba(0,0,0,0.5); z-index: 25;
|
||||
}
|
||||
|
||||
@keyframes float {
|
||||
|
|
@ -45,6 +47,12 @@
|
|||
50% { opacity: 0.5; }
|
||||
}
|
||||
.badge-pulse { animation: pulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite; }
|
||||
@media (max-width: 1023px) {
|
||||
.sidebar-desktop { display: none !important; }
|
||||
.main-content { margin-left: 0 !important; }
|
||||
.header-bar { left: 0 !important; }
|
||||
}
|
||||
|
||||
|
||||
.sidebar-bg {
|
||||
background: linear-gradient(160deg, #0f2010 0%, #0a1a0b 50%, #0d1e0e 100%);
|
||||
|
|
@ -60,10 +68,22 @@
|
|||
<body class="font-sans antialiased bg-gray-50">
|
||||
<div class="min-h-screen flex">
|
||||
|
||||
<!-- Sidebar -->
|
||||
<!-- Mobile Overlay -->
|
||||
<div x-show="mobileOpen"
|
||||
x-transition:enter="transition ease-out duration-200"
|
||||
x-transition:enter-start="opacity-0"
|
||||
x-transition:enter-end="opacity-100"
|
||||
x-transition:leave="transition ease-in duration-200"
|
||||
x-transition:leave-start="opacity-100"
|
||||
x-transition:leave-end="opacity-0"
|
||||
class="sidebar-overlay lg:hidden"
|
||||
@click="mobileOpen = false">
|
||||
</div>
|
||||
|
||||
<!-- Sidebar Desktop -->
|
||||
<aside
|
||||
:class="sidebarOpen ? 'w-64' : 'w-20'"
|
||||
class="sidebar-transition sidebar-bg text-white fixed h-full z-30 flex flex-col shadow-2xl"
|
||||
class="sidebar-transition sidebar-bg text-white fixed h-full z-30 flex-col shadow-2xl sidebar-desktop" style="display:flex;"
|
||||
>
|
||||
<!-- Logo -->
|
||||
<div class="p-6 border-b border-green-900/40">
|
||||
|
|
@ -133,23 +153,85 @@ class="flex items-center px-4 py-3 rounded-xl hover:bg-green-800/30 {{ request()
|
|||
</div>
|
||||
</aside>
|
||||
|
||||
<!-- Sidebar Mobile Drawer -->
|
||||
<aside
|
||||
x-show="mobileOpen"
|
||||
x-transition:enter="transition ease-out duration-300"
|
||||
x-transition:enter-start="-translate-x-full"
|
||||
x-transition:enter-end="translate-x-0"
|
||||
x-transition:leave="transition ease-in duration-200"
|
||||
x-transition:leave-start="translate-x-0"
|
||||
x-transition:leave-end="-translate-x-full"
|
||||
class="sidebar-bg text-white fixed h-full z-30 flex flex-col shadow-2xl w-72 lg:hidden"
|
||||
>
|
||||
<div class="p-6 border-b border-green-900/40">
|
||||
<div class="flex items-center justify-between">
|
||||
<div class="flex items-center space-x-3">
|
||||
<div class="logo-float">
|
||||
<div class="w-10 h-10 rounded-xl overflow-hidden shadow-lg flex-shrink-0">
|
||||
<img src="{{ asset('asset/images/ori_nobg.png') }}" class="w-full h-full object-cover" alt="Logo">
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<h1 class="text-lg font-bold bg-gradient-to-r from-green-400 to-green-200 bg-clip-text text-transparent">Cek Kopi</h1>
|
||||
<p class="text-xs text-green-300/70">Super Admin</p>
|
||||
</div>
|
||||
</div>
|
||||
<button @click="mobileOpen = false" class="p-2 rounded-lg hover:bg-green-800/30 transition-colors">
|
||||
<svg class="w-5 h-5 text-green-300" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12"/>
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<nav class="flex-1 px-4 py-6 space-y-2 overflow-y-auto">
|
||||
<a href="{{ route('super-admin.dashboard') }}"
|
||||
class="flex items-center px-4 py-3 rounded-xl hover:bg-green-800/30 {{ request()->routeIs('super-admin.dashboard') ? 'bg-green-700/50 ring-1 ring-green-400/60' : '' }} group">
|
||||
<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"/>
|
||||
</svg>
|
||||
</div>
|
||||
<span class="ml-3 font-semibold text-gray-200">Dashboard</span>
|
||||
</a>
|
||||
</nav>
|
||||
<div class="p-4 border-t border-green-900/40">
|
||||
<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="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"/>
|
||||
</svg>
|
||||
</div>
|
||||
<span class="ml-3 font-semibold text-red-400">Logout</span>
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
</aside>
|
||||
|
||||
<!-- Main Content -->
|
||||
<div :class="sidebarOpen ? 'ml-64' : 'ml-20'" class="flex-1 sidebar-transition">
|
||||
<div :class="sidebarOpen ? 'lg:ml-64' : 'lg:ml-20'" class="flex-1 sidebar-transition ml-0 lg:ml-64 min-w-0">
|
||||
|
||||
<!-- 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">
|
||||
<header class="bg-white border-b border-gray-200 fixed top-0 right-0 z-20 shadow-sm header-bar" style="left:16rem;"
|
||||
style="transition: left 0.3s cubic-bezier(0.4, 0, 0.2, 1);">
|
||||
<div class="px-4 lg: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>
|
||||
<div class="flex items-center gap-3">
|
||||
<button @click="mobileOpen = true" class="lg:hidden p-2 rounded-lg hover:bg-gray-100 transition-colors">
|
||||
<svg class="w-6 h-6 text-gray-700" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 6h16M4 12h16M4 18h16"/>
|
||||
</svg>
|
||||
</button>
|
||||
<h2 class="text-xl lg:text-2xl font-bold text-gray-800">@yield('page-title', 'Dashboard')</h2>
|
||||
</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-500 to-green-700 flex items-center justify-center text-white font-bold shadow-lg">
|
||||
<a href="{{ route('profile.edit') }}" class="flex items-center space-x-2 lg:space-x-3 px-2 lg: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-8 h-8 lg:w-10 lg:h-10 rounded-full bg-gradient-to-br from-green-500 to-green-700 flex items-center justify-center text-white font-bold shadow-lg text-sm">
|
||||
{{ substr(Auth::user()->nama, 0, 1) }}
|
||||
</div>
|
||||
<div class="text-left">
|
||||
<div class="text-left hidden sm:block">
|
||||
<p class="text-sm font-bold text-gray-800">{{ Auth::user()->nama }}</p>
|
||||
<p class="text-xs text-green-600 font-semibold uppercase">Super Admin</p>
|
||||
</div>
|
||||
|
|
@ -160,14 +242,14 @@ class="flex items-center px-4 py-3 rounded-xl hover:bg-green-800/30 {{ request()
|
|||
</header>
|
||||
|
||||
<!-- Page Content -->
|
||||
<main class="pt-28">
|
||||
<div class="p-8 page-content">
|
||||
<main style="padding-top: 73px;">
|
||||
<div class="p-4 lg:p-8 page-content">
|
||||
@yield('content')
|
||||
</div>
|
||||
</main>
|
||||
|
||||
<!-- Footer -->
|
||||
<footer class="px-8 py-6 bg-white border-t border-gray-200">
|
||||
<footer class="px-4 lg: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>
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}" x-data="{ sidebarOpen: true }" x-cloak>
|
||||
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}" x-data="{ sidebarOpen: true, mobileOpen: false }">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
|
|
@ -16,7 +16,6 @@
|
|||
<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; }
|
||||
|
|
@ -25,7 +24,10 @@
|
|||
::-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);
|
||||
transition: width 0.3s cubic-bezier(0.4, 0, 0.2, 1), margin-left 0.3s cubic-bezier(0.4, 0, 0.2, 1), transform 0.3s cubic-bezier(0.4, 0, 0.2, 1);
|
||||
}
|
||||
.sidebar-overlay {
|
||||
position: fixed; inset: 0; background: rgba(0,0,0,0.5); z-index: 25;
|
||||
}
|
||||
|
||||
@keyframes float {
|
||||
|
|
@ -45,6 +47,11 @@
|
|||
50% { opacity: 0.5; }
|
||||
}
|
||||
.badge-pulse { animation: pulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite; }
|
||||
@media (max-width: 1023px) {
|
||||
.sidebar-desktop { display: none !important; }
|
||||
.main-content { margin-left: 0 !important; }
|
||||
.header-bar { left: 0 !important; }
|
||||
}
|
||||
</style>
|
||||
|
||||
@stack('styles')
|
||||
|
|
@ -52,11 +59,23 @@
|
|||
<body class="font-sans antialiased bg-gray-50">
|
||||
<div class="min-h-screen flex">
|
||||
|
||||
<!-- Sidebar -->
|
||||
<!-- Mobile Overlay -->
|
||||
<div x-show="mobileOpen"
|
||||
x-transition:enter="transition ease-out duration-200"
|
||||
x-transition:enter-start="opacity-0"
|
||||
x-transition:enter-end="opacity-100"
|
||||
x-transition:leave="transition ease-in duration-200"
|
||||
x-transition:leave-start="opacity-100"
|
||||
x-transition:leave-end="opacity-0"
|
||||
class="sidebar-overlay lg:hidden"
|
||||
@click="mobileOpen = false">
|
||||
</div>
|
||||
|
||||
<!-- Sidebar Desktop -->
|
||||
<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"
|
||||
>
|
||||
class="sidebar-transition bg-gradient-to-b from-gray-900 via-gray-800 to-gray-900 text-white fixed h-full z-30 flex-col shadow-2xl sidebar-desktop"
|
||||
style="display:flex;">
|
||||
<!-- Logo -->
|
||||
<div class="p-6 border-b border-gray-700">
|
||||
<div class="flex items-center justify-between">
|
||||
|
|
@ -178,23 +197,134 @@ class="flex items-center px-3 py-2 rounded-lg hover:bg-gray-700 {{ request()->ro
|
|||
</div>
|
||||
</aside>
|
||||
|
||||
<!-- Sidebar Mobile Drawer -->
|
||||
<aside
|
||||
x-show="mobileOpen"
|
||||
x-transition:enter="transition ease-out duration-300"
|
||||
x-transition:enter-start="-translate-x-full"
|
||||
x-transition:enter-end="translate-x-0"
|
||||
x-transition:leave="transition ease-in duration-200"
|
||||
x-transition:leave-start="translate-x-0"
|
||||
x-transition:leave-end="-translate-x-full"
|
||||
class="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 w-72 lg:hidden"
|
||||
>
|
||||
<!-- Logo -->
|
||||
<div class="p-6 border-b border-gray-700">
|
||||
<div class="flex items-center justify-between">
|
||||
<div class="flex items-center space-x-3">
|
||||
<div class="logo-float">
|
||||
<div class="w-10 h-10 rounded-xl overflow-hidden shadow-lg flex-shrink-0">
|
||||
<img src="{{ asset('asset/images/ori_nobg.png') }}" class="w-full h-full object-cover" alt="Logo">
|
||||
</div>
|
||||
</div>
|
||||
<h1 class="text-lg font-bold bg-gradient-to-r from-green-400 to-green-200 bg-clip-text text-transparent">Cek Kopi</h1>
|
||||
</div>
|
||||
<button @click="mobileOpen = false" 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="M6 18L18 6M6 6l12 12"/>
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Nav (sama seperti desktop) -->
|
||||
<nav class="flex-1 px-4 py-6 space-y-2 overflow-y-auto">
|
||||
<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="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"/>
|
||||
</svg>
|
||||
</div>
|
||||
<span class="ml-3 font-semibold">Dashboard</span>
|
||||
</a>
|
||||
|
||||
<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="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"/>
|
||||
</svg>
|
||||
</div>
|
||||
<span class="ml-3 font-semibold flex-1 text-left">Diagnosa</span>
|
||||
<svg :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"/>
|
||||
</svg>
|
||||
</button>
|
||||
<div x-show="diagnosaOpen" 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>
|
||||
|
||||
<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="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"/>
|
||||
</svg>
|
||||
</div>
|
||||
<span class="ml-3 font-semibold flex-1 text-left">Artikel</span>
|
||||
<svg :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"/>
|
||||
</svg>
|
||||
</button>
|
||||
<div x-show="artikelOpen" 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="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"/>
|
||||
</svg>
|
||||
</div>
|
||||
<span class="ml-3 font-semibold text-red-400">Logout</span>
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
</aside>
|
||||
|
||||
<!-- Main Content -->
|
||||
<div :class="sidebarOpen ? 'ml-64' : 'ml-20'" class="flex-1 sidebar-transition">
|
||||
<div class="flex-1 sidebar-transition main-content" style="margin-left:16rem;">
|
||||
|
||||
<!-- 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">
|
||||
<header class="bg-white border-b border-gray-200 fixed top-0 right-0 z-20 shadow-sm header-bar"
|
||||
style="left:16rem; transition: left 0.3s cubic-bezier(0.4, 0, 0.2, 1);">
|
||||
<div class="px-4 lg: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>
|
||||
<div class="flex items-center gap-3">
|
||||
<!-- Hamburger mobile -->
|
||||
<button @click="mobileOpen = true" class="lg:hidden p-2 rounded-lg hover:bg-gray-100 transition-colors">
|
||||
<svg class="w-6 h-6 text-gray-700" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 6h16M4 12h16M4 18h16"/>
|
||||
</svg>
|
||||
</button>
|
||||
<h2 class="text-xl lg:text-2xl font-bold text-gray-800">@yield('page-title', 'Dashboard')</h2>
|
||||
</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">
|
||||
<a href="{{ route('profile.edit') }}" class="flex items-center space-x-2 lg:space-x-3 px-2 lg: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-8 h-8 lg:w-10 lg: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 text-sm">
|
||||
{{ substr(Auth::user()->nama, 0, 1) }}
|
||||
</div>
|
||||
<div class="text-left">
|
||||
<div class="text-left hidden sm:block">
|
||||
<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>
|
||||
|
|
@ -205,14 +335,14 @@ class="flex items-center px-3 py-2 rounded-lg hover:bg-gray-700 {{ request()->ro
|
|||
</header>
|
||||
|
||||
<!-- Page Content -->
|
||||
<main class="pt-28">
|
||||
<div class="p-8 page-content">
|
||||
<main style="padding-top: 73px;">
|
||||
<div class="p-4 lg:p-8 page-content">
|
||||
@yield('content')
|
||||
</div>
|
||||
</main>
|
||||
|
||||
<!-- Footer -->
|
||||
<footer class="px-8 py-6 bg-white border-t border-gray-200">
|
||||
<footer class="px-4 lg:px-8 py-6 bg-white border-t border-gray-200">
|
||||
<div class="text-center text-sm text-gray-600">
|
||||
© {{ date('Y') }} Cek Kopi by Evi. All rights reserved.
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -3,220 +3,254 @@
|
|||
@section('page-title', 'Dashboard')
|
||||
@section('page-subtitle', 'Selamat datang kembali, ' . Auth::user()->nama)
|
||||
|
||||
@push('styles')
|
||||
<style>
|
||||
.dash-root { font-family: 'Sora', sans-serif; }
|
||||
|
||||
/* ── Welcome Banner ── */
|
||||
.dash-banner {
|
||||
background: linear-gradient(130deg, #1a4d2e 0%, #2d7a4f 60%, #38a169 100%);
|
||||
border-radius: 14px;
|
||||
padding: 1.25rem 1.5rem;
|
||||
display: flex; align-items: center; justify-content: space-between;
|
||||
gap: 1rem; flex-wrap: wrap;
|
||||
position: relative; overflow: hidden;
|
||||
margin-bottom: 1.25rem;
|
||||
}
|
||||
.dash-banner::before {
|
||||
content: '';
|
||||
position: absolute; top: -40px; right: -40px;
|
||||
width: 160px; height: 160px; border-radius: 50%;
|
||||
background: rgba(255,255,255,.06); pointer-events: none;
|
||||
}
|
||||
.dash-banner::after {
|
||||
content: '';
|
||||
position: absolute; bottom: -30px; right: 60px;
|
||||
width: 100px; height: 100px; border-radius: 50%;
|
||||
background: rgba(255,255,255,.04); pointer-events: none;
|
||||
}
|
||||
.banner-left { display: flex; align-items: center; gap: .85rem; position: relative; z-index: 1; }
|
||||
.banner-avatar {
|
||||
width: 40px; height: 40px; border-radius: 50%;
|
||||
background: rgba(255,255,255,.15); border: 1.5px solid rgba(255,255,255,.25);
|
||||
display: flex; align-items: center; justify-content: center; flex-shrink: 0;
|
||||
}
|
||||
.banner-title { font-size: 1rem; font-weight: 700; color: #fff; line-height: 1.3; }
|
||||
.banner-sub { font-size: .78rem; color: rgba(255,255,255,.65); margin-top: 1px; }
|
||||
.banner-clock {
|
||||
position: relative; z-index: 1;
|
||||
display: flex; align-items: center; gap: .4rem;
|
||||
background: rgba(0,0,0,.18); border-radius: 999px;
|
||||
padding: .35rem .85rem; font-size: .75rem; color: rgba(255,255,255,.8);
|
||||
}
|
||||
|
||||
/* ── Stat Cards ── */
|
||||
.stat-grid {
|
||||
display: grid; grid-template-columns: repeat(4, 1fr);
|
||||
gap: .85rem; margin-bottom: 1.25rem;
|
||||
}
|
||||
@media (max-width: 900px) { .stat-grid { grid-template-columns: repeat(2, 1fr); } }
|
||||
@media (max-width: 500px) { .stat-grid { grid-template-columns: 1fr; } }
|
||||
|
||||
.stat-card {
|
||||
background: #fff; border-radius: 12px;
|
||||
border: 1px solid rgba(29,77,46,.09);
|
||||
padding: 1rem 1.1rem;
|
||||
box-shadow: 0 1px 6px rgba(29,77,46,.06);
|
||||
display: flex; align-items: center; gap: .9rem;
|
||||
transition: box-shadow .2s, transform .2s;
|
||||
}
|
||||
.stat-card:hover { box-shadow: 0 4px 18px rgba(29,77,46,.12); transform: translateY(-1px); }
|
||||
|
||||
.stat-icon {
|
||||
width: 38px; height: 38px; border-radius: 9px; flex-shrink: 0;
|
||||
display: flex; align-items: center; justify-content: center;
|
||||
background: #f0fdf4;
|
||||
}
|
||||
.stat-body { flex: 1; min-width: 0; }
|
||||
.stat-label { font-size: .68rem; font-weight: 600; color: #6b7f72; text-transform: uppercase; letter-spacing: .05em; }
|
||||
.stat-value { font-size: 1.55rem; font-weight: 800; color: #1a4d2e; line-height: 1.2; margin-top: 1px; }
|
||||
.stat-desc { font-size: .68rem; color: #9aada0; margin-top: 2px; }
|
||||
|
||||
/* ── Table Card ── */
|
||||
.table-card {
|
||||
background: #fff; border-radius: 14px;
|
||||
border: 1px solid rgba(29,77,46,.08);
|
||||
box-shadow: 0 1px 6px rgba(29,77,46,.06);
|
||||
overflow: hidden;
|
||||
}
|
||||
.table-hdr {
|
||||
display: flex; align-items: center; justify-content: space-between;
|
||||
padding: .9rem 1.2rem; border-bottom: 1px solid #f0fdf4;
|
||||
}
|
||||
.table-hdr-left { display: flex; align-items: center; gap: .6rem; }
|
||||
.table-hdr-icon {
|
||||
width: 30px; height: 30px; border-radius: 8px;
|
||||
background: #f0fdf4; display: flex; align-items: center; justify-content: center;
|
||||
}
|
||||
.table-hdr-title { font-size: .9rem; font-weight: 700; color: #1a4d2e; }
|
||||
.btn-view-all {
|
||||
display: inline-flex; align-items: center; gap: .3rem;
|
||||
padding: .4rem .9rem; border-radius: 8px; font-size: .75rem; font-weight: 600;
|
||||
background: #f0fdf4; color: #2d7a4f; text-decoration: none;
|
||||
border: 1px solid #d1fae5; transition: all .15s;
|
||||
}
|
||||
.btn-view-all:hover { background: #dcfce7; color: #1a4d2e; }
|
||||
|
||||
/* Table */
|
||||
.dash-table { width: 100%; border-collapse: collapse; font-size: .8rem; }
|
||||
.dash-table th {
|
||||
padding: .6rem 1rem; text-align: left;
|
||||
font-size: .68rem; font-weight: 700; text-transform: uppercase;
|
||||
letter-spacing: .06em; color: #6b7f72;
|
||||
background: #f9fafb; border-bottom: 1px solid #f0fdf4;
|
||||
}
|
||||
.dash-table td { padding: .65rem 1rem; border-bottom: 1px solid #f9fafb; color: #374151; }
|
||||
.dash-table tr:last-child td { border-bottom: none; }
|
||||
.dash-table tr:hover td { background: #fafffe; }
|
||||
|
||||
.user-avatar {
|
||||
width: 30px; height: 30px; border-radius: 50%; flex-shrink: 0;
|
||||
background: linear-gradient(135deg, #2d7a4f, #38a169);
|
||||
display: flex; align-items: center; justify-content: center;
|
||||
font-size: .72rem; font-weight: 800; color: #fff;
|
||||
}
|
||||
.user-cell { display: flex; align-items: center; gap: .6rem; }
|
||||
.user-name { font-weight: 600; color: #111827; }
|
||||
|
||||
/* Role badges — all green tones */
|
||||
.badge {
|
||||
display: inline-flex; align-items: center; gap: .25rem;
|
||||
padding: .2rem .65rem; border-radius: 999px;
|
||||
font-size: .68rem; font-weight: 700;
|
||||
}
|
||||
.badge-sa { background: #1a4d2e; color: #fff; }
|
||||
.badge-admin { background: #dcfce7; color: #166534; border: 1px solid #bbf7d0; }
|
||||
.badge-user { background: #f0fdf4; color: #4d7c5a; border: 1px solid #d1fae5; }
|
||||
|
||||
.empty-state { padding: 2.5rem; text-align: center; color: #9aada0; }
|
||||
.empty-state svg { margin: 0 auto .75rem; display: block; }
|
||||
</style>
|
||||
@endpush
|
||||
|
||||
@section('content')
|
||||
<div class="max-w-7xl mx-auto space-y-6">
|
||||
<div class="dash-root">
|
||||
|
||||
<!-- Welcome Card with Gradient -->
|
||||
<div class="bg-gradient-to-r from-green-600 via-green-700 to-green-800 overflow-hidden shadow-xl sm:rounded-2xl transform hover:scale-[1.01] transition duration-300">
|
||||
<div class="p-8 text-white relative overflow-hidden">
|
||||
<!-- Decorative circles -->
|
||||
<div class="absolute -right-10 -top-10 w-40 h-40 bg-white opacity-10 rounded-full"></div>
|
||||
<div class="absolute -right-5 -bottom-5 w-32 h-32 bg-white opacity-10 rounded-full"></div>
|
||||
|
||||
<div class="relative z-10">
|
||||
<div class="flex items-center mb-4">
|
||||
<div class="bg-white bg-opacity-20 rounded-full p-3 mr-4">
|
||||
<svg class="w-8 h-8" fill="currentColor" viewBox="0 0 20 20">
|
||||
<path d="M10 9a3 3 0 100-6 3 3 0 000 6zm-7 9a7 7 0 1114 0H3z"/>
|
||||
</svg>
|
||||
{{-- Banner --}}
|
||||
<div class="dash-banner">
|
||||
<div class="banner-left">
|
||||
<div class="banner-avatar">
|
||||
<svg width="18" height="18" fill="none" stroke="#fff" viewBox="0 0 24 24" stroke-width="2"><path stroke-linecap="round" stroke-linejoin="round" d="M16 7a4 4 0 11-8 0 4 4 0 018 0zM12 14a7 7 0 00-7 7h14a7 7 0 00-7-7z"/></svg>
|
||||
</div>
|
||||
<div>
|
||||
<h3 class="text-3xl font-bold">Selamat Datang Kembali!</h3>
|
||||
<p class="text-green-100 text-lg mt-1">{{ Auth::user()->nama }}</p>
|
||||
<div class="banner-title">Selamat Datang, {{ Auth::user()->nama }}</div>
|
||||
<div class="banner-sub">Super Administrator — Sistem Pakar Kopi</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mt-4 flex items-center space-x-4">
|
||||
<div class="flex items-center bg-white bg-opacity-20 rounded-full px-4 py-2">
|
||||
<svg class="w-5 h-5 mr-2" fill="currentColor" viewBox="0 0 20 20">
|
||||
<path fill-rule="evenodd" d="M10 18a8 8 0 100-16 8 8 0 000 16zm1-12a1 1 0 10-2 0v4a1 1 0 00.293.707l2.828 2.829a1 1 0 101.415-1.415L11 9.586V6z" clip-rule="evenodd"/>
|
||||
</svg>
|
||||
<span class="text-sm" id="realtime-clock"></span>
|
||||
<div class="banner-clock">
|
||||
<svg width="13" height="13" fill="none" stroke="currentColor" viewBox="0 0 24 24" stroke-width="2"><circle cx="12" cy="12" r="10"/><path stroke-linecap="round" d="M12 6v6l4 2"/></svg>
|
||||
<span id="realtime-clock"></span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{-- Stat Cards --}}
|
||||
<div class="stat-grid">
|
||||
<div class="stat-card">
|
||||
<div class="stat-icon">
|
||||
<svg width="18" height="18" fill="none" stroke="#2d7a4f" viewBox="0 0 24 24" stroke-width="2"><path stroke-linecap="round" stroke-linejoin="round" d="M17 20H7m10 0v-2a3 3 0 00-3-3H10a3 3 0 00-3 3v2m0 0H2v-2a3 3 0 015.356-1.857M7 20v-2m5-10a4 4 0 110-8 4 4 0 010 8z"/></svg>
|
||||
</div>
|
||||
<div class="stat-body">
|
||||
<div class="stat-label">Total Users</div>
|
||||
<div class="stat-value">{{ \App\Models\User::count() }}</div>
|
||||
<div class="stat-desc">Semua pengguna</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="stat-card">
|
||||
<div class="stat-icon">
|
||||
<svg width="18" height="18" fill="none" stroke="#2d7a4f" viewBox="0 0 24 24" stroke-width="2"><path stroke-linecap="round" stroke-linejoin="round" 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"/></svg>
|
||||
</div>
|
||||
<div class="stat-body">
|
||||
<div class="stat-label">Super Admin</div>
|
||||
<div class="stat-value">{{ \App\Models\User::where('role', 'super_admin')->count() }}</div>
|
||||
<div class="stat-desc">Full access</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="stat-card">
|
||||
<div class="stat-icon">
|
||||
<svg width="18" height="18" fill="none" stroke="#2d7a4f" viewBox="0 0 24 24" stroke-width="2"><path stroke-linecap="round" stroke-linejoin="round" d="M5.121 17.804A13.937 13.937 0 0112 16c2.5 0 4.847.655 6.879 1.804M15 10a3 3 0 11-6 0 3 3 0 016 0z"/></svg>
|
||||
</div>
|
||||
<div class="stat-body">
|
||||
<div class="stat-label">Admin</div>
|
||||
<div class="stat-value">{{ \App\Models\User::where('role', 'admin')->count() }}</div>
|
||||
<div class="stat-desc">Administrator</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="stat-card">
|
||||
<div class="stat-icon">
|
||||
<svg width="18" height="18" fill="none" stroke="#2d7a4f" viewBox="0 0 24 24" stroke-width="2"><path stroke-linecap="round" stroke-linejoin="round" d="M17 20h5v-2a3 3 0 00-5.356-1.857M17 20H7m10 0v-2c0-.656-.126-1.283-.356-1.857M7 20H2v-2a3 3 0 015.356-1.857M7 20v-2c0-.656.126-1.283.356-1.857m0 0a5.002 5.002 0 019.288 0M15 7a3 3 0 11-6 0 3 3 0 016 0z"/></svg>
|
||||
</div>
|
||||
<div class="stat-body">
|
||||
<div class="stat-label">Regular Users</div>
|
||||
<div class="stat-value">{{ \App\Models\User::where('role', 'user')->count() }}</div>
|
||||
<div class="stat-desc">Pengguna biasa</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Statistics Cards -->
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-6">
|
||||
<!-- Total Users -->
|
||||
<div class="bg-white overflow-hidden shadow-lg sm:rounded-2xl transform hover:scale-105 transition duration-300 hover:shadow-2xl">
|
||||
<div class="p-6">
|
||||
<div class="flex items-center justify-between">
|
||||
<div class="flex-1">
|
||||
<p class="text-sm font-semibold text-gray-500 uppercase tracking-wide">Total Users</p>
|
||||
<h3 class="text-4xl font-bold text-gray-800 mt-2">{{ \App\Models\User::count() }}</h3>
|
||||
<p class="text-xs text-gray-500 mt-2">Semua pengguna terdaftar</p>
|
||||
{{-- Recent Users --}}
|
||||
<div class="table-card">
|
||||
<div class="table-hdr">
|
||||
<div class="table-hdr-left">
|
||||
<div class="table-hdr-icon">
|
||||
<svg width="14" height="14" fill="none" stroke="#2d7a4f" viewBox="0 0 24 24" stroke-width="2"><path stroke-linecap="round" stroke-linejoin="round" d="M12 8v4l3 3m6-3a9 9 0 11-18 0 9 9 0 0118 0z"/></svg>
|
||||
</div>
|
||||
<div class="bg-gradient-to-br from-blue-400 to-blue-600 rounded-2xl p-4 shadow-lg">
|
||||
<svg class="w-10 h-10 text-white" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2.5" d="M12 4.354a4 4 0 110 5.292M15 21H3v-1a6 6 0 0112 0v1zm0 0h6v-1a6 6 0 00-9-5.197M13 7a4 4 0 11-8 0 4 4 0 018 0z"></path>
|
||||
</svg>
|
||||
<span class="table-hdr-title">Recent Users</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mt-4 flex items-center text-green-600">
|
||||
<svg class="w-4 h-4 mr-1" fill="currentColor" viewBox="0 0 20 20">
|
||||
<path fill-rule="evenodd" d="M12 7a1 1 0 110-2h5a1 1 0 011 1v5a1 1 0 11-2 0V8.414l-4.293 4.293a1 1 0 01-1.414 0L8 10.414l-4.293 4.293a1 1 0 01-1.414-1.414l5-5a1 1 0 011.414 0L11 10.586 14.586 7H12z" clip-rule="evenodd"/>
|
||||
</svg>
|
||||
<span class="text-xs font-semibold">Aktif</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Super Admins -->
|
||||
<div class="bg-white overflow-hidden shadow-lg sm:rounded-2xl transform hover:scale-105 transition duration-300 hover:shadow-2xl">
|
||||
<div class="p-6">
|
||||
<div class="flex items-center justify-between">
|
||||
<div class="flex-1">
|
||||
<p class="text-sm font-semibold text-gray-500 uppercase tracking-wide">Super Admins</p>
|
||||
<h3 class="text-4xl font-bold text-gray-800 mt-2">{{ \App\Models\User::where('role', 'super_admin')->count() }}</h3>
|
||||
<p class="text-xs text-gray-500 mt-2">Administrator tertinggi</p>
|
||||
</div>
|
||||
<div class="bg-gradient-to-br from-red-400 to-red-600 rounded-2xl p-4 shadow-lg">
|
||||
<svg class="w-10 h-10 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 class="mt-4 flex items-center text-red-600">
|
||||
<svg class="w-4 h-4 mr-1" fill="currentColor" viewBox="0 0 20 20">
|
||||
<path fill-rule="evenodd" d="M5 9V7a5 5 0 0110 0v2a2 2 0 012 2v5a2 2 0 01-2 2H5a2 2 0 01-2-2v-5a2 2 0 012-2zm8-2v2H7V7a3 3 0 016 0z" clip-rule="evenodd"/>
|
||||
</svg>
|
||||
<span class="text-xs font-semibold">Full Access</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Admins -->
|
||||
<div class="bg-white overflow-hidden shadow-lg sm:rounded-2xl transform hover:scale-105 transition duration-300 hover:shadow-2xl">
|
||||
<div class="p-6">
|
||||
<div class="flex items-center justify-between">
|
||||
<div class="flex-1">
|
||||
<p class="text-sm font-semibold text-gray-500 uppercase tracking-wide">Admins</p>
|
||||
<h3 class="text-4xl font-bold text-gray-800 mt-2">{{ \App\Models\User::where('role', 'admin')->count() }}</h3>
|
||||
<p class="text-xs text-gray-500 mt-2">Administrator biasa</p>
|
||||
</div>
|
||||
<div class="bg-gradient-to-br from-green-400 to-green-600 rounded-2xl p-4 shadow-lg">
|
||||
<svg class="w-10 h-10 text-white" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2.5" d="M5.121 17.804A13.937 13.937 0 0112 16c2.5 0 4.847.655 6.879 1.804M15 10a3 3 0 11-6 0 3 3 0 016 0zm6 2a9 9 0 11-18 0 9 9 0 0118 0z"></path>
|
||||
</svg>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mt-4 flex items-center text-green-600">
|
||||
<svg class="w-4 h-4 mr-1" fill="currentColor" viewBox="0 0 20 20">
|
||||
<path fill-rule="evenodd" d="M6.267 3.455a3.066 3.066 0 001.745-.723 3.066 3.066 0 013.976 0 3.066 3.066 0 001.745.723 3.066 3.066 0 012.812 2.812c.051.643.304 1.254.723 1.745a3.066 3.066 0 010 3.976 3.066 3.066 0 00-.723 1.745 3.066 3.066 0 01-2.812 2.812 3.066 3.066 0 00-1.745.723 3.066 3.066 0 01-3.976 0 3.066 3.066 0 00-1.745-.723 3.066 3.066 0 01-2.812-2.812 3.066 3.066 0 00-.723-1.745 3.066 3.066 0 010-3.976 3.066 3.066 0 00.723-1.745 3.066 3.066 0 012.812-2.812zm7.44 5.252a1 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-xs font-semibold">Verified</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Regular Users -->
|
||||
<div class="bg-white overflow-hidden shadow-lg sm:rounded-2xl transform hover:scale-105 transition duration-300 hover:shadow-2xl">
|
||||
<div class="p-6">
|
||||
<div class="flex items-center justify-between">
|
||||
<div class="flex-1">
|
||||
<p class="text-sm font-semibold text-gray-500 uppercase tracking-wide">Regular Users</p>
|
||||
<h3 class="text-4xl font-bold text-gray-800 mt-2">{{ \App\Models\User::where('role', 'user')->count() }}</h3>
|
||||
<p class="text-xs text-gray-500 mt-2">Pengguna biasa</p>
|
||||
</div>
|
||||
<div class="bg-gradient-to-br from-purple-400 to-purple-600 rounded-2xl p-4 shadow-lg">
|
||||
<svg class="w-10 h-10 text-white" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2.5" d="M17 20h5v-2a3 3 0 00-5.356-1.857M17 20H7m10 0v-2c0-.656-.126-1.283-.356-1.857M7 20H2v-2a3 3 0 015.356-1.857M7 20v-2c0-.656.126-1.283.356-1.857m0 0a5.002 5.002 0 019.288 0M15 7a3 3 0 11-6 0 3 3 0 016 0zm6 3a2 2 0 11-4 0 2 2 0 014 0zM7 10a2 2 0 11-4 0 2 2 0 014 0z"></path>
|
||||
</svg>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mt-4 flex items-center text-purple-600">
|
||||
<svg class="w-4 h-4 mr-1" fill="currentColor" viewBox="0 0 20 20">
|
||||
<path d="M13 6a3 3 0 11-6 0 3 3 0 016 0zM18 8a2 2 0 11-4 0 2 2 0 014 0zM14 15a4 4 0 00-8 0v3h8v-3zM6 8a2 2 0 11-4 0 2 2 0 014 0zM16 18v-3a5.972 5.972 0 00-.75-2.906A3.005 3.005 0 0119 15v3h-3zM4.75 12.094A5.973 5.973 0 004 15v3H1v-3a3 3 0 013.75-2.906z"/>
|
||||
</svg>
|
||||
<span class="text-xs font-semibold">Community</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Recent Users Table -->
|
||||
<div class="bg-white overflow-hidden shadow-xl sm:rounded-2xl">
|
||||
<div class="p-8">
|
||||
<div class="flex justify-between items-center 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-2xl font-bold text-gray-800">Recent Users</h3>
|
||||
</div>
|
||||
<a href="{{ route('super-admin.users.index') }}" class="flex items-center px-4 py-2 bg-gradient-to-r from-green-500 to-green-600 text-white text-sm font-semibold rounded-xl hover:from-green-600 hover:to-green-700 transition-all shadow-lg hover:shadow-xl">
|
||||
View All
|
||||
<svg class="w-4 h-4 ml-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5l7 7-7 7"></path>
|
||||
</svg>
|
||||
<a href="{{ route('super-admin.users.index') }}" class="btn-view-all">
|
||||
Lihat Semua
|
||||
<svg width="12" height="12" fill="none" stroke="currentColor" viewBox="0 0 24 24" stroke-width="2.5"><path stroke-linecap="round" stroke-linejoin="round" d="M9 5l7 7-7 7"/></svg>
|
||||
</a>
|
||||
</div>
|
||||
<div class="overflow-x-auto rounded-xl border border-green-100">
|
||||
<table class="min-w-full divide-y divide-green-100">
|
||||
<thead class="bg-green-50">
|
||||
|
||||
<div style="overflow-x:auto;">
|
||||
<table class="dash-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="px-6 py-4 text-left text-xs font-bold text-green-600 uppercase tracking-wider">Username</th>
|
||||
<th class="px-6 py-4 text-left text-xs font-bold text-green-600 uppercase tracking-wider">Nama</th>
|
||||
<th class="px-6 py-4 text-left text-xs font-bold text-green-600 uppercase tracking-wider">Email</th>
|
||||
<th class="px-6 py-4 text-left text-xs font-bold text-green-600 uppercase tracking-wider">Role</th>
|
||||
<th class="px-6 py-4 text-left text-xs font-bold text-green-600 uppercase tracking-wider">Registered</th>
|
||||
<th>Username</th>
|
||||
<th>Nama</th>
|
||||
<th>Email</th>
|
||||
<th>Role</th>
|
||||
<th>Bergabung</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody class="bg-white divide-y divide-green-50">
|
||||
<tbody>
|
||||
@forelse(\App\Models\User::latest()->take(5)->get() as $user)
|
||||
<tr class="hover:bg-green-50 transition-colors">
|
||||
<td class="px-6 py-4 whitespace-nowrap">
|
||||
<div class="flex items-center">
|
||||
<div class="flex-shrink-0 h-10 w-10 bg-gradient-to-br from-green-400 to-green-600 rounded-full flex items-center justify-center text-white font-bold">
|
||||
{{ strtoupper(substr($user->username, 0, 1)) }}
|
||||
</div>
|
||||
<div class="ml-4">
|
||||
<div class="text-sm font-semibold text-gray-900">{{ $user->username }}</div>
|
||||
</div>
|
||||
<tr>
|
||||
<td>
|
||||
<div class="user-cell">
|
||||
<div class="user-avatar">{{ strtoupper(substr($user->username, 0, 1)) }}</div>
|
||||
<span class="user-name">{{ $user->username }}</span>
|
||||
</div>
|
||||
</td>
|
||||
<td class="px-6 py-4 whitespace-nowrap">
|
||||
<div class="text-sm text-gray-900 font-medium">{{ $user->nama }}</div>
|
||||
</td>
|
||||
<td class="px-6 py-4 whitespace-nowrap">
|
||||
<div class="text-sm text-gray-600">{{ $user->email }}</div>
|
||||
</td>
|
||||
<td class="px-6 py-4 whitespace-nowrap">
|
||||
<td>{{ $user->nama }}</td>
|
||||
<td style="color:#6b7280;">{{ $user->email }}</td>
|
||||
<td>
|
||||
@if($user->role === 'super_admin')
|
||||
<span class="px-3 py-1 inline-flex text-xs leading-5 font-bold rounded-full bg-gradient-to-r from-yellow-500 to-yellow-600 text-white shadow-md">
|
||||
⭐ Super Admin
|
||||
</span>
|
||||
<span class="badge badge-sa">Super Admin</span>
|
||||
@elseif($user->role === 'admin')
|
||||
<span class="px-3 py-1 inline-flex text-xs leading-5 font-bold rounded-full bg-gradient-to-r from-green-500 to-green-600 text-white shadow-md">
|
||||
👤 Admin
|
||||
</span>
|
||||
<span class="badge badge-admin">Admin</span>
|
||||
@else
|
||||
<span class="px-3 py-1 inline-flex text-xs leading-5 font-bold rounded-full bg-gradient-to-r from-blue-400 to-blue-500 text-white shadow-md">
|
||||
👥 User
|
||||
</span>
|
||||
<span class="badge badge-user">User</span>
|
||||
@endif
|
||||
</td>
|
||||
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-600">
|
||||
<div class="flex items-center">
|
||||
<svg class="w-4 h-4 mr-2 text-green-400" fill="currentColor" viewBox="0 0 20 20">
|
||||
<path fill-rule="evenodd" d="M10 18a8 8 0 100-16 8 8 0 000 16zm1-12a1 1 0 10-2 0v4a1 1 0 00.293.707l2.828 2.829a1 1 0 101.415-1.415L11 9.586V6z" clip-rule="evenodd"/>
|
||||
</svg>
|
||||
{{ $user->created_at->diffForHumans() }}
|
||||
</div>
|
||||
</td>
|
||||
<td style="color:#6b7280; font-size:.75rem;">{{ $user->created_at->diffForHumans() }}</td>
|
||||
</tr>
|
||||
@empty
|
||||
<tr>
|
||||
<td colspan="5" class="px-6 py-8 text-center">
|
||||
<div class="text-green-300">
|
||||
<svg class="w-12 h-12 mx-auto mb-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M20 13V6a2 2 0 00-2-2H6a2 2 0 00-2 2v7m16 0v5a2 2 0 01-2 2H6a2 2 0 01-2-2v-5m16 0h-2.586a1 1 0 00-.707.293l-2.414 2.414a1 1 0 01-.707.293h-3.172a1 1 0 01-.707-.293l-2.414-2.414A1 1 0 006.586 13H4"></path>
|
||||
</svg>
|
||||
<p class="text-lg font-semibold">Belum ada data user</p>
|
||||
<td colspan="5">
|
||||
<div class="empty-state">
|
||||
<svg width="36" height="36" fill="none" stroke="#c4d6c8" viewBox="0 0 24 24" stroke-width="1.5"><path stroke-linecap="round" stroke-linejoin="round" d="M20 13V6a2 2 0 00-2-2H6a2 2 0 00-2 2v7m16 0v5a2 2 0 01-2 2H6a2 2 0 01-2-2v-5m16 0h-2.586a1 1 0 00-.707.293l-2.414 2.414a1 1 0 01-.707.293h-3.172a1 1 0 01-.707-.293l-2.414-2.414A1 1 0 006.586 13H4"/></svg>
|
||||
Belum ada data user
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
|
|
@ -225,17 +259,16 @@
|
|||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<script>
|
||||
function updateClock() {
|
||||
</div>
|
||||
|
||||
<script>
|
||||
function updateClock() {
|
||||
const now = new Date();
|
||||
const options = { weekday: 'long', day: 'numeric', month: 'long', year: '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>
|
||||
|
||||
}
|
||||
updateClock();
|
||||
setInterval(updateClock, 1000);
|
||||
</script>
|
||||
@endsection
|
||||
|
|
@ -4,153 +4,116 @@
|
|||
@section('page-subtitle', 'Buat akun pengguna baru')
|
||||
|
||||
@section('content')
|
||||
|
||||
<style>
|
||||
@import url('https://fonts.googleapis.com/css2?family=Plus+Jakarta+Sans:wght@300;400;500;600;700;800&display=swap');
|
||||
.form-page { font-family: 'Sora', sans-serif; }
|
||||
|
||||
.create-page * { font-family: 'Plus Jakarta Sans', sans-serif; }
|
||||
|
||||
.form-wrapper { max-width: 680px; margin: 0 auto; }
|
||||
.form-wrapper { max-width: 640px; margin: 0 auto; }
|
||||
|
||||
.form-card {
|
||||
background: white; border-radius: 28px;
|
||||
border: 1px solid #dcfce7;
|
||||
box-shadow: 0 8px 40px rgba(22, 163, 74, 0.1);
|
||||
background: #fff; border-radius: 14px;
|
||||
border: 1px solid rgba(29,77,46,.09);
|
||||
box-shadow: 0 1px 6px rgba(29,77,46,.06);
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.form-hero {
|
||||
padding: 32px 36px 28px;
|
||||
background: linear-gradient(135deg, #14532d 0%, #166534 50%, #16a34a 100%);
|
||||
.form-hdr {
|
||||
padding: 1.1rem 1.4rem;
|
||||
background: linear-gradient(130deg, #1a4d2e 0%, #2d7a4f 60%, #38a169 100%);
|
||||
display: flex; align-items: center; gap: .75rem;
|
||||
position: relative; overflow: hidden;
|
||||
}
|
||||
.form-hero::before {
|
||||
content: ''; position: absolute; top: -40px; right: -40px;
|
||||
width: 160px; height: 160px;
|
||||
background: rgba(255,255,255,0.07); border-radius: 50%;
|
||||
.form-hdr::before {
|
||||
content: ''; position: absolute; top: -30px; right: -30px;
|
||||
width: 120px; height: 120px; border-radius: 50%;
|
||||
background: rgba(255,255,255,.06); pointer-events: none;
|
||||
}
|
||||
.form-hero::after {
|
||||
content: ''; position: absolute; bottom: -30px; right: 80px;
|
||||
width: 100px; height: 100px;
|
||||
background: rgba(255,255,255,0.05); border-radius: 50%;
|
||||
}
|
||||
.hero-icon {
|
||||
width: 52px; height: 52px; border-radius: 16px;
|
||||
background: rgba(255,255,255,0.18);
|
||||
.form-hdr-icon {
|
||||
width: 36px; height: 36px; border-radius: 9px; flex-shrink: 0;
|
||||
background: rgba(255,255,255,.15);
|
||||
display: flex; align-items: center; justify-content: center;
|
||||
margin-bottom: 16px; backdrop-filter: blur(10px);
|
||||
}
|
||||
.hero-icon svg { width: 26px; height: 26px; color: white; }
|
||||
.form-hero h2 { font-size: 1.4rem; font-weight: 800; color: white; letter-spacing: -0.3px; }
|
||||
.form-hero p { color: rgba(255,255,255,0.65); font-size: 0.85rem; margin-top: 4px; }
|
||||
.form-hdr-title { font-size: .95rem; font-weight: 700; color: #fff; }
|
||||
.form-hdr-sub { font-size: .75rem; color: rgba(255,255,255,.6); margin-top: 1px; }
|
||||
|
||||
.form-body { padding: 32px 36px; }
|
||||
.form-body { padding: 1.4rem; }
|
||||
|
||||
.form-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 20px; }
|
||||
.form-group { display: flex; flex-direction: column; gap: 6px; }
|
||||
.form-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 1rem; }
|
||||
.form-group { display: flex; flex-direction: column; gap: 5px; }
|
||||
.form-group.full { grid-column: 1 / -1; }
|
||||
|
||||
.form-label {
|
||||
font-size: 0.78rem; font-weight: 700; color: #374151;
|
||||
text-transform: uppercase; letter-spacing: 0.5px;
|
||||
font-size: .72rem; font-weight: 700; color: #374151;
|
||||
text-transform: uppercase; letter-spacing: .05em;
|
||||
}
|
||||
.label-optional { font-size: 0.72rem; font-weight: 500; color: #9ca3af; text-transform: none; letter-spacing: 0; }
|
||||
.label-opt { font-size: .7rem; font-weight: 400; color: #9ca3af; text-transform: none; letter-spacing: 0; }
|
||||
|
||||
.form-input {
|
||||
width: 100%; padding: 12px 16px;
|
||||
border: 1.5px solid #e5e7eb; border-radius: 14px;
|
||||
font-size: 0.88rem; color: #1a1a2e; background: #fafafa;
|
||||
transition: all 0.2s ease; outline: none;
|
||||
font-family: 'Plus Jakarta Sans', sans-serif;
|
||||
.form-input, .form-select {
|
||||
width: 100%; padding: .6rem .85rem;
|
||||
border: 1.5px solid #e5e7eb; border-radius: 9px;
|
||||
font-size: .82rem; color: #111827; background: #fafafa;
|
||||
transition: all .2s; outline: none;
|
||||
font-family: 'Sora', sans-serif;
|
||||
}
|
||||
.form-input:focus {
|
||||
border-color: #16a34a; background: white;
|
||||
box-shadow: 0 0 0 4px rgba(22, 163, 74, 0.08);
|
||||
.form-input:focus, .form-select:focus {
|
||||
border-color: #16a34a; background: #fff;
|
||||
box-shadow: 0 0 0 3px rgba(22,163,74,.08);
|
||||
}
|
||||
.form-input.error { border-color: #ef4444; background: #fff5f5; }
|
||||
.form-input.is-error, .form-select.is-error { border-color: #ef4444; background: #fff5f5; }
|
||||
.form-input::placeholder { color: #c4c4cc; }
|
||||
|
||||
.form-select {
|
||||
width: 100%; padding: 12px 16px;
|
||||
border: 1.5px solid #e5e7eb; border-radius: 14px;
|
||||
font-size: 0.88rem; color: #1a1a2e; background: #fafafa;
|
||||
transition: all 0.2s ease; outline: none; cursor: pointer;
|
||||
font-family: 'Plus Jakarta Sans', sans-serif; appearance: none;
|
||||
appearance: none; cursor: pointer;
|
||||
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 24 24' stroke='%2316a34a'%3E%3Cpath stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='M19 9l-7 7-7-7'/%3E%3C/svg%3E");
|
||||
background-repeat: no-repeat; background-position: right 14px center;
|
||||
background-size: 16px; padding-right: 44px;
|
||||
}
|
||||
.form-select:focus {
|
||||
border-color: #16a34a; background-color: white;
|
||||
box-shadow: 0 0 0 4px rgba(22, 163, 74, 0.08);
|
||||
background-repeat: no-repeat; background-position: right 10px center;
|
||||
background-size: 14px; padding-right: 36px;
|
||||
}
|
||||
|
||||
.error-msg { font-size: 0.75rem; color: #ef4444; font-weight: 500; }
|
||||
.error-msg { font-size: .72rem; color: #ef4444; font-weight: 500; }
|
||||
|
||||
.password-box {
|
||||
background: linear-gradient(135deg, #fffbeb 0%, #fef3c7 100%);
|
||||
border: 1.5px solid #fde68a; border-radius: 18px;
|
||||
padding: 20px; margin: 4px 0;
|
||||
background: #f9fafb; border: 1.5px solid #e5e7eb; border-radius: 10px;
|
||||
padding: 1rem; margin-top: 1rem;
|
||||
}
|
||||
.password-box-label {
|
||||
display: flex; align-items: center; gap: 7px;
|
||||
font-size: 0.78rem; font-weight: 700; color: #92400e;
|
||||
margin-bottom: 16px; text-transform: uppercase; letter-spacing: 0.5px;
|
||||
display: flex; align-items: center; gap: .4rem;
|
||||
font-size: .72rem; font-weight: 700; color: #6b7280;
|
||||
text-transform: uppercase; letter-spacing: .05em; margin-bottom: .75rem;
|
||||
}
|
||||
.password-box-label svg { width: 14px; height: 14px; }
|
||||
.password-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 16px; }
|
||||
.password-input {
|
||||
width: 100%; padding: 12px 16px;
|
||||
border: 1.5px solid #fde68a; border-radius: 12px;
|
||||
font-size: 0.88rem; color: #1a1a2e; background: white;
|
||||
transition: all 0.2s ease; outline: none;
|
||||
font-family: 'Plus Jakarta Sans', sans-serif;
|
||||
}
|
||||
.password-input:focus {
|
||||
border-color: #16a34a;
|
||||
box-shadow: 0 0 0 4px rgba(22, 163, 74, 0.08);
|
||||
}
|
||||
.password-input.error { border-color: #ef4444; }
|
||||
.password-input::placeholder { color: #c4c4cc; }
|
||||
.password-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 1rem; }
|
||||
|
||||
.divider { height: 1px; background: linear-gradient(to right, transparent, #dcfce7, transparent); margin: 8px 0; }
|
||||
.divider { height: 1px; background: #f0fdf4; margin: 1.2rem 0; }
|
||||
|
||||
.form-actions { display: flex; align-items: center; justify-content: space-between; padding-top: 8px; margin-top: 8px; }
|
||||
.form-actions { display: flex; align-items: center; justify-content: space-between; }
|
||||
.btn-cancel {
|
||||
display: inline-flex; align-items: center; gap: 8px;
|
||||
padding: 11px 20px; color: #6b7280; font-weight: 600; font-size: 0.85rem;
|
||||
border-radius: 14px; text-decoration: none;
|
||||
background: #f9fafb; border: 1.5px solid #e5e7eb; transition: all 0.2s ease;
|
||||
display: inline-flex; align-items: center; gap: .4rem;
|
||||
padding: .55rem 1rem; border-radius: 8px; font-size: .8rem; font-weight: 600;
|
||||
color: #6b7280; background: #f9fafb; border: 1.5px solid #e5e7eb;
|
||||
text-decoration: none; transition: all .15s;
|
||||
}
|
||||
.btn-cancel:hover { background: #f3f4f6; color: #374151; }
|
||||
.btn-cancel svg { width: 15px; height: 15px; }
|
||||
.btn-submit {
|
||||
display: inline-flex; align-items: center; gap: 8px;
|
||||
padding: 13px 28px;
|
||||
background: linear-gradient(135deg, #16a34a 0%, #15803d 100%);
|
||||
color: white; font-weight: 700; font-size: 0.88rem;
|
||||
border-radius: 14px; border: none; cursor: pointer;
|
||||
box-shadow: 0 4px 15px rgba(22, 163, 74, 0.35);
|
||||
transition: all 0.3s ease;
|
||||
font-family: 'Plus Jakarta Sans', sans-serif; letter-spacing: 0.2px;
|
||||
display: inline-flex; align-items: center; gap: .4rem;
|
||||
padding: .6rem 1.2rem; border-radius: 8px; font-size: .82rem; font-weight: 700;
|
||||
background: linear-gradient(135deg, #2d7a4f, #16a34a);
|
||||
color: #fff; border: none; cursor: pointer;
|
||||
box-shadow: 0 2px 8px rgba(22,163,74,.3); transition: all .2s;
|
||||
font-family: 'Sora', sans-serif;
|
||||
}
|
||||
.btn-submit:hover {
|
||||
transform: translateY(-2px);
|
||||
box-shadow: 0 8px 25px rgba(22, 163, 74, 0.45);
|
||||
}
|
||||
.btn-submit svg { width: 16px; height: 16px; }
|
||||
.btn-submit:hover { transform: translateY(-1px); box-shadow: 0 4px 14px rgba(22,163,74,.4); }
|
||||
</style>
|
||||
|
||||
<div class="create-page">
|
||||
<div class="form-page">
|
||||
<div class="form-wrapper">
|
||||
<div class="form-card">
|
||||
|
||||
<div class="form-hero">
|
||||
<div class="hero-icon">
|
||||
<svg fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M18 9v3m0 0v3m0-3h3m-3 0h-3m-2-5a4 4 0 11-8 0 4 4 0 018 0zM3 20a6 6 0 0112 0v1H3v-1z"/></svg>
|
||||
<div class="form-hdr">
|
||||
<div class="form-hdr-icon">
|
||||
<svg width="16" height="16" fill="none" stroke="#fff" viewBox="0 0 24 24" stroke-width="2"><path stroke-linecap="round" stroke-linejoin="round" d="M18 9v3m0 0v3m0-3h3m-3 0h-3m-2-5a4 4 0 11-8 0 4 4 0 018 0zM3 20a6 6 0 0112 0v1H3v-1z"/></svg>
|
||||
</div>
|
||||
<div>
|
||||
<div class="form-hdr-title">Tambah Pengguna Baru</div>
|
||||
<div class="form-hdr-sub">Lengkapi semua informasi untuk membuat akun baru</div>
|
||||
</div>
|
||||
<h2>Form Pengguna Baru</h2>
|
||||
<p>Lengkapi semua informasi untuk membuat akun baru</p>
|
||||
</div>
|
||||
|
||||
<form method="POST" action="{{ route('super-admin.users.store') }}" class="form-body">
|
||||
|
|
@ -161,61 +124,58 @@
|
|||
<label for="username" class="form-label">Username</label>
|
||||
<input id="username" name="username" type="text"
|
||||
value="{{ old('username') }}" placeholder="contoh: johndoe"
|
||||
class="form-input @error('username') error @enderror"
|
||||
class="form-input @error('username') is-error @enderror"
|
||||
required autofocus />
|
||||
@error('username')<p class="error-msg">{{ $message }}</p>@enderror
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="nama" class="form-label">Nama Lengkap</label>
|
||||
<input id="nama" name="nama" type="text"
|
||||
value="{{ old('nama') }}" placeholder="Nama lengkap"
|
||||
class="form-input @error('nama') error @enderror" required />
|
||||
class="form-input @error('nama') is-error @enderror" required />
|
||||
@error('nama')<p class="error-msg">{{ $message }}</p>@enderror
|
||||
</div>
|
||||
|
||||
<div class="form-group full">
|
||||
<label for="email" class="form-label">Email</label>
|
||||
<input id="email" name="email" type="email"
|
||||
value="{{ old('email') }}" placeholder="contoh@email.com"
|
||||
class="form-input @error('email') error @enderror" required />
|
||||
class="form-input @error('email') is-error @enderror" required />
|
||||
@error('email')<p class="error-msg">{{ $message }}</p>@enderror
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="password-box" style="margin-top:20px;">
|
||||
<div class="password-box">
|
||||
<div class="password-box-label">
|
||||
<svg fill="currentColor" viewBox="0 0 20 20"><path fill-rule="evenodd" d="M5 9V7a5 5 0 0110 0v2a2 2 0 012 2v5a2 2 0 01-2 2H5a2 2 0 01-2-2v-5a2 2 0 012-2zm8-2v2H7V7a3 3 0 016 0z" clip-rule="evenodd"/></svg>
|
||||
<svg width="12" height="12" fill="currentColor" viewBox="0 0 20 20"><path fill-rule="evenodd" d="M5 9V7a5 5 0 0110 0v2a2 2 0 012 2v5a2 2 0 01-2 2H5a2 2 0 01-2-2v-5a2 2 0 012-2zm8-2v2H7V7a3 3 0 016 0z" clip-rule="evenodd"/></svg>
|
||||
Keamanan Akun
|
||||
</div>
|
||||
<div class="password-grid">
|
||||
<div class="form-group">
|
||||
<label for="password" class="form-label" style="color:#92400e;">Password</label>
|
||||
<label for="password" class="form-label">Password</label>
|
||||
<input id="password" name="password" type="password"
|
||||
placeholder="Min. 8 karakter"
|
||||
class="password-input @error('password') error @enderror" required />
|
||||
class="form-input @error('password') is-error @enderror" required />
|
||||
@error('password')<p class="error-msg">{{ $message }}</p>@enderror
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="password_confirmation" class="form-label" style="color:#92400e;">Konfirmasi</label>
|
||||
<label for="password_confirmation" class="form-label">Konfirmasi</label>
|
||||
<input id="password_confirmation" name="password_confirmation" type="password"
|
||||
placeholder="Ulangi password" class="password-input" required />
|
||||
placeholder="Ulangi password" class="form-input" required />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-grid" style="margin-top:20px;">
|
||||
<div class="form-grid" style="margin-top:1rem;">
|
||||
<div class="form-group">
|
||||
<label for="no_hp" class="form-label">No HP <span class="label-optional">(opsional)</span></label>
|
||||
<label for="no_hp" class="form-label">No HP <span class="label-opt">(opsional)</span></label>
|
||||
<input id="no_hp" name="no_hp" type="text"
|
||||
value="{{ old('no_hp') }}" placeholder="08xxxxxxxxxx"
|
||||
class="form-input @error('no_hp') error @enderror" />
|
||||
class="form-input @error('no_hp') is-error @enderror" />
|
||||
@error('no_hp')<p class="error-msg">{{ $message }}</p>@enderror
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="role" class="form-label">Role</label>
|
||||
<select id="role" name="role" class="form-select @error('role') error @enderror" required>
|
||||
<select id="role" name="role" class="form-select @error('role') is-error @enderror" required>
|
||||
<option value="">Pilih Role</option>
|
||||
<option value="super_admin" {{ old('role') == 'super_admin' ? 'selected' : '' }}>Super Admin</option>
|
||||
<option value="admin" {{ old('role') == 'admin' ? 'selected' : '' }}>Admin</option>
|
||||
|
|
@ -225,15 +185,15 @@ class="form-input @error('no_hp') error @enderror" />
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<div class="divider" style="margin-top:28px;"></div>
|
||||
<div class="divider"></div>
|
||||
|
||||
<div class="form-actions">
|
||||
<a href="{{ route('super-admin.users.index') }}" class="btn-cancel">
|
||||
<svg fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10 19l-7-7m0 0l7-7m-7 7h18"/></svg>
|
||||
<svg width="13" height="13" fill="none" stroke="currentColor" viewBox="0 0 24 24" stroke-width="2"><path stroke-linecap="round" stroke-linejoin="round" d="M10 19l-7-7m0 0l7-7m-7 7h18"/></svg>
|
||||
Batal
|
||||
</a>
|
||||
<button type="submit" class="btn-submit">
|
||||
<svg fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2.5" d="M5 13l4 4L19 7"/></svg>
|
||||
<svg width="13" height="13" fill="none" stroke="currentColor" viewBox="0 0 24 24" stroke-width="2.5"><path stroke-linecap="round" stroke-linejoin="round" d="M5 13l4 4L19 7"/></svg>
|
||||
Simpan Pengguna
|
||||
</button>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -4,186 +4,139 @@
|
|||
@section('page-subtitle', 'Ubah data akun: ' . $user->nama)
|
||||
|
||||
@section('content')
|
||||
|
||||
<style>
|
||||
@import url('https://fonts.googleapis.com/css2?family=Plus+Jakarta+Sans:wght@300;400;500;600;700;800&display=swap');
|
||||
.form-page { font-family: 'Sora', sans-serif; }
|
||||
|
||||
.edit-page * { font-family: 'Plus Jakarta Sans', sans-serif; }
|
||||
|
||||
.form-wrapper { max-width: 720px; margin: 0 auto; }
|
||||
.form-wrapper { max-width: 640px; margin: 0 auto; }
|
||||
|
||||
.form-card {
|
||||
background: white; border-radius: 28px;
|
||||
border: 1px solid #dcfce7;
|
||||
box-shadow: 0 8px 40px rgba(22, 163, 74, 0.1);
|
||||
background: #fff; border-radius: 14px;
|
||||
border: 1px solid rgba(29,77,46,.09);
|
||||
box-shadow: 0 1px 6px rgba(29,77,46,.06);
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.form-hero {
|
||||
padding: 28px 36px;
|
||||
background: linear-gradient(135deg, #14532d 0%, #166534 40%, #22c55e 100%);
|
||||
.form-hdr {
|
||||
padding: 1.1rem 1.4rem;
|
||||
background: linear-gradient(130deg, #1a4d2e 0%, #2d7a4f 60%, #38a169 100%);
|
||||
display: flex; align-items: center; justify-content: space-between; gap: 1rem;
|
||||
position: relative; overflow: hidden;
|
||||
}
|
||||
.form-hero::before {
|
||||
content: ''; position: absolute; top: -50px; right: -30px;
|
||||
width: 180px; height: 180px;
|
||||
background: rgba(255,255,255,0.07); border-radius: 50%;
|
||||
.form-hdr::before {
|
||||
content: ''; position: absolute; top: -30px; right: -30px;
|
||||
width: 120px; height: 120px; border-radius: 50%;
|
||||
background: rgba(255,255,255,.06); pointer-events: none;
|
||||
}
|
||||
.form-hero::after {
|
||||
content: ''; position: absolute; bottom: -20px; left: 200px;
|
||||
width: 80px; height: 80px;
|
||||
background: rgba(255,255,255,0.05); border-radius: 50%;
|
||||
}
|
||||
|
||||
.hero-top { display: flex; align-items: center; justify-content: space-between; position: relative; z-index: 1; }
|
||||
.hero-left { display: flex; align-items: center; gap: 14px; }
|
||||
.hero-icon {
|
||||
width: 48px; height: 48px; border-radius: 14px;
|
||||
background: rgba(255,255,255,0.18);
|
||||
.form-hdr-left { display: flex; align-items: center; gap: .75rem; position: relative; z-index: 1; }
|
||||
.form-hdr-icon {
|
||||
width: 36px; height: 36px; border-radius: 9px; flex-shrink: 0;
|
||||
background: rgba(255,255,255,.15);
|
||||
display: flex; align-items: center; justify-content: center;
|
||||
backdrop-filter: blur(10px);
|
||||
}
|
||||
.hero-icon svg { width: 24px; height: 24px; color: white; }
|
||||
.hero-title { font-size: 1.3rem; font-weight: 800; color: white; letter-spacing: -0.3px; }
|
||||
.hero-id { color: rgba(255,255,255,0.6); font-size: 0.8rem; margin-top: 2px; }
|
||||
.form-hdr-title { font-size: .95rem; font-weight: 700; color: #fff; }
|
||||
.form-hdr-sub { font-size: .72rem; color: rgba(255,255,255,.6); margin-top: 1px; }
|
||||
|
||||
.user-badge {
|
||||
display: flex; align-items: center; gap: 10px;
|
||||
background: rgba(255,255,255,0.15);
|
||||
backdrop-filter: blur(10px);
|
||||
border: 1px solid rgba(255,255,255,0.2);
|
||||
border-radius: 14px; padding: 10px 16px;
|
||||
.user-chip {
|
||||
display: flex; align-items: center; gap: .55rem;
|
||||
background: rgba(0,0,0,.18); border-radius: 999px;
|
||||
padding: .35rem .75rem .35rem .45rem;
|
||||
position: relative; z-index: 1; flex-shrink: 0;
|
||||
}
|
||||
.badge-avatar {
|
||||
width: 36px; height: 36px; border-radius: 10px;
|
||||
.chip-avatar {
|
||||
width: 26px; height: 26px; border-radius: 50%; flex-shrink: 0;
|
||||
background: rgba(255,255,255,.25);
|
||||
display: flex; align-items: center; justify-content: center;
|
||||
font-size: 0.85rem; font-weight: 800; color: white;
|
||||
font-size: .7rem; font-weight: 800; color: #fff;
|
||||
}
|
||||
.badge-avatar.super { background: linear-gradient(135deg, #f59e0b, #d97706); }
|
||||
.badge-avatar.admin { background: linear-gradient(135deg, #22c55e, #15803d); }
|
||||
.badge-avatar.user { background: linear-gradient(135deg, #4ade80, #16a34a); }
|
||||
.badge-name { font-size: 0.85rem; font-weight: 700; color: white; }
|
||||
.badge-uname { font-size: 0.72rem; color: rgba(255,255,255,0.6); margin-top: 1px; }
|
||||
.chip-name { font-size: .78rem; font-weight: 600; color: #fff; }
|
||||
.chip-uname { font-size: .68rem; color: rgba(255,255,255,.55); }
|
||||
|
||||
.form-body { padding: 32px 36px; }
|
||||
.form-body { padding: 1.4rem; }
|
||||
|
||||
.form-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 20px; }
|
||||
.form-group { display: flex; flex-direction: column; gap: 6px; }
|
||||
.form-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 1rem; }
|
||||
.form-group { display: flex; flex-direction: column; gap: 5px; }
|
||||
.form-group.full { grid-column: 1 / -1; }
|
||||
|
||||
.form-label {
|
||||
font-size: 0.78rem; font-weight: 700; color: #374151;
|
||||
text-transform: uppercase; letter-spacing: 0.5px;
|
||||
font-size: .72rem; font-weight: 700; color: #374151;
|
||||
text-transform: uppercase; letter-spacing: .05em;
|
||||
}
|
||||
.label-optional { font-size: 0.72rem; font-weight: 500; color: #9ca3af; text-transform: none; letter-spacing: 0; }
|
||||
.label-opt { font-size: .7rem; font-weight: 400; color: #9ca3af; text-transform: none; letter-spacing: 0; }
|
||||
|
||||
.form-input {
|
||||
width: 100%; padding: 12px 16px;
|
||||
border: 1.5px solid #e5e7eb; border-radius: 14px;
|
||||
font-size: 0.88rem; color: #1a1a2e; background: #fafafa;
|
||||
transition: all 0.2s ease; outline: none;
|
||||
font-family: 'Plus Jakarta Sans', sans-serif;
|
||||
.form-input, .form-select {
|
||||
width: 100%; padding: .6rem .85rem;
|
||||
border: 1.5px solid #e5e7eb; border-radius: 9px;
|
||||
font-size: .82rem; color: #111827; background: #fafafa;
|
||||
transition: all .2s; outline: none;
|
||||
font-family: 'Sora', sans-serif;
|
||||
}
|
||||
.form-input:focus {
|
||||
border-color: #16a34a; background: white;
|
||||
box-shadow: 0 0 0 4px rgba(22, 163, 74, 0.08);
|
||||
.form-input:focus, .form-select:focus {
|
||||
border-color: #16a34a; background: #fff;
|
||||
box-shadow: 0 0 0 3px rgba(22,163,74,.08);
|
||||
}
|
||||
.form-input.error { border-color: #ef4444; background: #fff5f5; }
|
||||
.form-input.is-error, .form-select.is-error { border-color: #ef4444; background: #fff5f5; }
|
||||
.form-input::placeholder { color: #c4c4cc; }
|
||||
|
||||
.form-select {
|
||||
width: 100%; padding: 12px 16px;
|
||||
border: 1.5px solid #e5e7eb; border-radius: 14px;
|
||||
font-size: 0.88rem; color: #1a1a2e; background: #fafafa;
|
||||
transition: all 0.2s ease; outline: none; cursor: pointer;
|
||||
font-family: 'Plus Jakarta Sans', sans-serif; appearance: none;
|
||||
appearance: none; cursor: pointer;
|
||||
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 24 24' stroke='%2316a34a'%3E%3Cpath stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='M19 9l-7 7-7-7'/%3E%3C/svg%3E");
|
||||
background-repeat: no-repeat; background-position: right 14px center;
|
||||
background-size: 16px; padding-right: 44px;
|
||||
}
|
||||
.form-select:focus {
|
||||
border-color: #16a34a; background-color: white;
|
||||
box-shadow: 0 0 0 4px rgba(22, 163, 74, 0.08);
|
||||
background-repeat: no-repeat; background-position: right 10px center;
|
||||
background-size: 14px; padding-right: 36px;
|
||||
}
|
||||
|
||||
.error-msg { font-size: 0.75rem; color: #ef4444; font-weight: 500; }
|
||||
.error-msg { font-size: .72rem; color: #ef4444; font-weight: 500; }
|
||||
|
||||
.password-box {
|
||||
background: linear-gradient(135deg, #fffbeb 0%, #fef9c3 100%);
|
||||
border: 1.5px solid #fde68a; border-radius: 18px;
|
||||
padding: 20px; margin: 4px 0;
|
||||
background: #f9fafb; border: 1.5px solid #e5e7eb; border-radius: 10px;
|
||||
padding: 1rem; margin-top: 1rem;
|
||||
}
|
||||
.password-box-label {
|
||||
display: flex; align-items: center; gap: 7px;
|
||||
font-size: 0.78rem; font-weight: 700; color: #92400e;
|
||||
margin-bottom: 16px; text-transform: uppercase; letter-spacing: 0.5px;
|
||||
display: flex; align-items: center; gap: .4rem;
|
||||
font-size: .72rem; font-weight: 700; color: #6b7280;
|
||||
text-transform: uppercase; letter-spacing: .05em; margin-bottom: .75rem;
|
||||
}
|
||||
.password-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 16px; }
|
||||
.password-input {
|
||||
width: 100%; padding: 12px 16px;
|
||||
border: 1.5px solid #fde68a; border-radius: 12px;
|
||||
font-size: 0.88rem; color: #1a1a2e; background: white;
|
||||
transition: all 0.2s ease; outline: none;
|
||||
font-family: 'Plus Jakarta Sans', sans-serif;
|
||||
}
|
||||
.password-input:focus {
|
||||
border-color: #16a34a;
|
||||
box-shadow: 0 0 0 4px rgba(22, 163, 74, 0.08);
|
||||
}
|
||||
.password-input.error { border-color: #ef4444; }
|
||||
.password-input::placeholder { color: #c4c4cc; }
|
||||
.password-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 1rem; }
|
||||
|
||||
.divider { height: 1px; background: linear-gradient(to right, transparent, #dcfce7, transparent); margin: 8px 0; }
|
||||
.divider { height: 1px; background: #f0fdf4; margin: 1.2rem 0; }
|
||||
|
||||
.form-actions { display: flex; align-items: center; justify-content: space-between; padding-top: 8px; margin-top: 8px; }
|
||||
.form-actions { display: flex; align-items: center; justify-content: space-between; }
|
||||
.btn-cancel {
|
||||
display: inline-flex; align-items: center; gap: 8px;
|
||||
padding: 11px 20px; color: #6b7280; font-weight: 600; font-size: 0.85rem;
|
||||
border-radius: 14px; text-decoration: none;
|
||||
background: #f9fafb; border: 1.5px solid #e5e7eb; transition: all 0.2s ease;
|
||||
display: inline-flex; align-items: center; gap: .4rem;
|
||||
padding: .55rem 1rem; border-radius: 8px; font-size: .8rem; font-weight: 600;
|
||||
color: #6b7280; background: #f9fafb; border: 1.5px solid #e5e7eb;
|
||||
text-decoration: none; transition: all .15s;
|
||||
}
|
||||
.btn-cancel:hover { background: #f3f4f6; color: #374151; }
|
||||
.btn-cancel svg { width: 15px; height: 15px; }
|
||||
.btn-submit {
|
||||
display: inline-flex; align-items: center; gap: 8px;
|
||||
padding: 13px 28px;
|
||||
background: linear-gradient(135deg, #16a34a 0%, #15803d 100%);
|
||||
color: white; font-weight: 700; font-size: 0.88rem;
|
||||
border-radius: 14px; border: none; cursor: pointer;
|
||||
box-shadow: 0 4px 15px rgba(22, 163, 74, 0.35);
|
||||
transition: all 0.3s ease;
|
||||
font-family: 'Plus Jakarta Sans', sans-serif; letter-spacing: 0.2px;
|
||||
display: inline-flex; align-items: center; gap: .4rem;
|
||||
padding: .6rem 1.2rem; border-radius: 8px; font-size: .82rem; font-weight: 700;
|
||||
background: linear-gradient(135deg, #2d7a4f, #16a34a);
|
||||
color: #fff; border: none; cursor: pointer;
|
||||
box-shadow: 0 2px 8px rgba(22,163,74,.3); transition: all .2s;
|
||||
font-family: 'Sora', sans-serif;
|
||||
}
|
||||
.btn-submit:hover {
|
||||
transform: translateY(-2px);
|
||||
box-shadow: 0 8px 25px rgba(22, 163, 74, 0.45);
|
||||
}
|
||||
.btn-submit svg { width: 16px; height: 16px; }
|
||||
.btn-submit:hover { transform: translateY(-1px); box-shadow: 0 4px 14px rgba(22,163,74,.4); }
|
||||
</style>
|
||||
|
||||
<div class="edit-page">
|
||||
<div class="form-page">
|
||||
<div class="form-wrapper">
|
||||
<div class="form-card">
|
||||
|
||||
<div class="form-hero">
|
||||
<div class="hero-top">
|
||||
<div class="hero-left">
|
||||
<div class="hero-icon">
|
||||
<svg fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2.5" 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"/></svg>
|
||||
<div class="form-hdr">
|
||||
<div class="form-hdr-left">
|
||||
<div class="form-hdr-icon">
|
||||
<svg width="16" height="16" fill="none" stroke="#fff" viewBox="0 0 24 24" stroke-width="2"><path stroke-linecap="round" stroke-linejoin="round" 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"/></svg>
|
||||
</div>
|
||||
<div>
|
||||
<div class="hero-title">Edit Pengguna</div>
|
||||
<div class="hero-id">ID #{{ $user->id }}</div>
|
||||
<div class="form-hdr-title">Edit Pengguna</div>
|
||||
<div class="form-hdr-sub">ID #{{ $user->id }}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="user-badge">
|
||||
<div class="badge-avatar {{ $user->role === 'super_admin' ? 'super' : ($user->role === 'admin' ? 'admin' : 'user') }}">
|
||||
{{ strtoupper(substr($user->nama, 0, 1)) }}
|
||||
</div>
|
||||
<div class="user-chip">
|
||||
<div class="chip-avatar">{{ strtoupper(substr($user->nama, 0, 1)) }}</div>
|
||||
<div>
|
||||
<div class="badge-name">{{ $user->nama }}</div>
|
||||
<div class="badge-uname">{{ $user->username }}</div>
|
||||
</div>
|
||||
<div class="chip-name">{{ $user->nama }}</div>
|
||||
<div class="chip-uname">{{ $user->username }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -196,61 +149,58 @@
|
|||
<label for="username" class="form-label">Username</label>
|
||||
<input id="username" name="username" type="text"
|
||||
value="{{ old('username', $user->username) }}"
|
||||
class="form-input @error('username') error @enderror"
|
||||
class="form-input @error('username') is-error @enderror"
|
||||
required autofocus />
|
||||
@error('username')<p class="error-msg">{{ $message }}</p>@enderror
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="nama" class="form-label">Nama Lengkap</label>
|
||||
<input id="nama" name="nama" type="text"
|
||||
value="{{ old('nama', $user->nama) }}"
|
||||
class="form-input @error('nama') error @enderror" required />
|
||||
class="form-input @error('nama') is-error @enderror" required />
|
||||
@error('nama')<p class="error-msg">{{ $message }}</p>@enderror
|
||||
</div>
|
||||
|
||||
<div class="form-group full">
|
||||
<label for="email" class="form-label">Email</label>
|
||||
<input id="email" name="email" type="email"
|
||||
value="{{ old('email', $user->email) }}"
|
||||
class="form-input @error('email') error @enderror" required />
|
||||
class="form-input @error('email') is-error @enderror" required />
|
||||
@error('email')<p class="error-msg">{{ $message }}</p>@enderror
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="password-box" style="margin-top:20px;">
|
||||
<div class="password-box">
|
||||
<div class="password-box-label">
|
||||
<svg width="14" height="14" fill="currentColor" viewBox="0 0 20 20"><path fill-rule="evenodd" d="M5 9V7a5 5 0 0110 0v2a2 2 0 012 2v5a2 2 0 01-2 2H5a2 2 0 01-2-2v-5a2 2 0 012-2zm8-2v2H7V7a3 3 0 016 0z" clip-rule="evenodd"/></svg>
|
||||
<svg width="12" height="12" fill="currentColor" viewBox="0 0 20 20"><path fill-rule="evenodd" d="M5 9V7a5 5 0 0110 0v2a2 2 0 012 2v5a2 2 0 01-2 2H5a2 2 0 01-2-2v-5a2 2 0 012-2zm8-2v2H7V7a3 3 0 016 0z" clip-rule="evenodd"/></svg>
|
||||
Kosongkan jika tidak ingin mengubah password
|
||||
</div>
|
||||
<div class="password-grid">
|
||||
<div class="form-group">
|
||||
<label for="password" class="form-label" style="color:#92400e;">Password Baru</label>
|
||||
<label for="password" class="form-label">Password Baru</label>
|
||||
<input id="password" name="password" type="password"
|
||||
placeholder="Min. 8 karakter"
|
||||
class="password-input @error('password') error @enderror" />
|
||||
class="form-input @error('password') is-error @enderror" />
|
||||
@error('password')<p class="error-msg">{{ $message }}</p>@enderror
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="password_confirmation" class="form-label" style="color:#92400e;">Konfirmasi</label>
|
||||
<label for="password_confirmation" class="form-label">Konfirmasi</label>
|
||||
<input id="password_confirmation" name="password_confirmation" type="password"
|
||||
placeholder="Ulangi password baru" class="password-input" />
|
||||
placeholder="Ulangi password baru" class="form-input" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-grid" style="margin-top:20px;">
|
||||
<div class="form-grid" style="margin-top:1rem;">
|
||||
<div class="form-group">
|
||||
<label for="no_hp" class="form-label">No HP <span class="label-optional">(opsional)</span></label>
|
||||
<label for="no_hp" class="form-label">No HP <span class="label-opt">(opsional)</span></label>
|
||||
<input id="no_hp" name="no_hp" type="text"
|
||||
value="{{ old('no_hp', $user->no_hp) }}" placeholder="08xxxxxxxxxx"
|
||||
class="form-input @error('no_hp') error @enderror" />
|
||||
class="form-input @error('no_hp') is-error @enderror" />
|
||||
@error('no_hp')<p class="error-msg">{{ $message }}</p>@enderror
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="role" class="form-label">Role</label>
|
||||
<select id="role" name="role" class="form-select @error('role') error @enderror" required>
|
||||
<select id="role" name="role" class="form-select @error('role') is-error @enderror" required>
|
||||
<option value="super_admin" {{ old('role', $user->role) == 'super_admin' ? 'selected' : '' }}>Super Admin</option>
|
||||
<option value="admin" {{ old('role', $user->role) == 'admin' ? 'selected' : '' }}>Admin</option>
|
||||
<option value="user" {{ old('role', $user->role) == 'user' ? 'selected' : '' }}>User</option>
|
||||
|
|
@ -259,15 +209,15 @@ class="form-input @error('no_hp') error @enderror" />
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<div class="divider" style="margin-top:28px;"></div>
|
||||
<div class="divider"></div>
|
||||
|
||||
<div class="form-actions">
|
||||
<a href="{{ route('super-admin.users.index') }}" class="btn-cancel">
|
||||
<svg fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10 19l-7-7m0 0l7-7m-7 7h18"/></svg>
|
||||
<svg width="13" height="13" fill="none" stroke="currentColor" viewBox="0 0 24 24" stroke-width="2"><path stroke-linecap="round" stroke-linejoin="round" d="M10 19l-7-7m0 0l7-7m-7 7h18"/></svg>
|
||||
Batal
|
||||
</a>
|
||||
<button type="submit" class="btn-submit">
|
||||
<svg fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2.5" d="M5 13l4 4L19 7"/></svg>
|
||||
<svg width="13" height="13" fill="none" stroke="currentColor" viewBox="0 0 24 24" stroke-width="2.5"><path stroke-linecap="round" stroke-linejoin="round" d="M5 13l4 4L19 7"/></svg>
|
||||
Update Pengguna
|
||||
</button>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -4,171 +4,126 @@
|
|||
@section('page-subtitle', 'Kelola semua akun pengguna sistem')
|
||||
|
||||
@section('content')
|
||||
|
||||
<style>
|
||||
@import url('https://fonts.googleapis.com/css2?family=Plus+Jakarta+Sans:wght@300;400;500;600;700;800&display=swap');
|
||||
.users-page { font-family: 'Sora', sans-serif; }
|
||||
|
||||
.users-page * { font-family: 'Plus Jakarta Sans', sans-serif; }
|
||||
|
||||
.alert-success {
|
||||
display: flex; align-items: center; gap: 12px;
|
||||
background: linear-gradient(135deg, #ecfdf5 0%, #d1fae5 100%);
|
||||
border: 1px solid #6ee7b7; color: #065f46;
|
||||
padding: 14px 20px; border-radius: 16px; margin-bottom: 20px;
|
||||
animation: slideDown 0.4s ease;
|
||||
.alert {
|
||||
display: flex; align-items: center; gap: 10px;
|
||||
padding: 11px 16px; border-radius: 10px; margin-bottom: 1rem;
|
||||
font-size: .82rem; font-weight: 600;
|
||||
}
|
||||
.alert-error {
|
||||
display: flex; align-items: center; gap: 12px;
|
||||
background: linear-gradient(135deg, #fef2f2 0%, #fecaca 100%);
|
||||
border: 1px solid #f87171; color: #7f1d1d;
|
||||
padding: 14px 20px; border-radius: 16px; margin-bottom: 20px;
|
||||
animation: slideDown 0.4s ease;
|
||||
}
|
||||
@keyframes slideDown {
|
||||
from { opacity: 0; transform: translateY(-10px); }
|
||||
to { opacity: 1; transform: translateY(0); }
|
||||
}
|
||||
|
||||
.btn-add {
|
||||
display: inline-flex; align-items: center; gap: 8px;
|
||||
padding: 12px 22px;
|
||||
background: linear-gradient(135deg, #16a34a 0%, #15803d 100%);
|
||||
color: white; font-weight: 700; font-size: 0.85rem;
|
||||
border-radius: 14px; text-decoration: none;
|
||||
box-shadow: 0 4px 15px rgba(22, 163, 74, 0.35);
|
||||
transition: all 0.3s ease; letter-spacing: 0.2px;
|
||||
}
|
||||
.btn-add:hover {
|
||||
transform: translateY(-2px);
|
||||
box-shadow: 0 8px 25px rgba(22, 163, 74, 0.45);
|
||||
color: white;
|
||||
}
|
||||
.btn-add svg { width: 16px; height: 16px; }
|
||||
.alert-success { background: #f0fdf4; border: 1px solid #bbf7d0; color: #166534; }
|
||||
.alert-error { background: #fef2f2; border: 1px solid #fecaca; color: #991b1b; }
|
||||
|
||||
.table-card {
|
||||
background: white; border-radius: 24px;
|
||||
border: 1px solid #dcfce7;
|
||||
box-shadow: 0 4px 24px rgba(22, 163, 74, 0.08);
|
||||
background: #fff; border-radius: 14px;
|
||||
border: 1px solid rgba(29,77,46,.09);
|
||||
box-shadow: 0 1px 6px rgba(29,77,46,.06);
|
||||
overflow: hidden;
|
||||
}
|
||||
.table-card-header {
|
||||
padding: 22px 28px; border-bottom: 1px solid #f0fdf4;
|
||||
.table-card-hdr {
|
||||
display: flex; align-items: center; justify-content: space-between;
|
||||
padding: .85rem 1.2rem; border-bottom: 1px solid #f0fdf4;
|
||||
}
|
||||
.table-card-header-left { display: flex; align-items: center; gap: 12px; }
|
||||
.table-card-header h3 { font-size: 1rem; font-weight: 700; color: #14532d; }
|
||||
.header-dot {
|
||||
width: 8px; height: 8px; border-radius: 50%;
|
||||
background: linear-gradient(135deg, #22c55e, #16a34a);
|
||||
box-shadow: 0 0 0 3px rgba(34, 197, 94, 0.2);
|
||||
}
|
||||
.table-card-hdr-left { display: flex; align-items: center; gap: .6rem; }
|
||||
.table-card-title { font-size: .9rem; font-weight: 700; color: #1a4d2e; }
|
||||
.count-badge {
|
||||
background: #dcfce7; color: #15803d;
|
||||
font-size: 0.72rem; font-weight: 700;
|
||||
padding: 3px 10px; border-radius: 20px;
|
||||
background: #f0fdf4; color: #2d7a4f; border: 1px solid #d1fae5;
|
||||
font-size: .68rem; font-weight: 700; padding: 2px 9px; border-radius: 999px;
|
||||
}
|
||||
|
||||
table { width: 100%; border-collapse: collapse; }
|
||||
thead tr { background: #f0fdf4; }
|
||||
thead th {
|
||||
padding: 12px 20px; text-align: left;
|
||||
font-size: 0.72rem; font-weight: 700; color: #4ade80;
|
||||
text-transform: uppercase; letter-spacing: 0.8px;
|
||||
border-bottom: 1px solid #dcfce7;
|
||||
.btn-add {
|
||||
display: inline-flex; align-items: center; gap: .4rem;
|
||||
padding: .45rem 1rem; border-radius: 8px; font-size: .78rem; font-weight: 700;
|
||||
background: linear-gradient(135deg, #2d7a4f, #16a34a);
|
||||
color: #fff; text-decoration: none;
|
||||
box-shadow: 0 2px 8px rgba(22,163,74,.25); transition: all .2s;
|
||||
}
|
||||
tbody tr { border-bottom: 1px solid #f7fef9; transition: background 0.15s ease; }
|
||||
tbody tr:last-child { border-bottom: none; }
|
||||
tbody tr:hover { background: #f0fdf4; }
|
||||
td { padding: 16px 20px; }
|
||||
.btn-add:hover { transform: translateY(-1px); box-shadow: 0 4px 14px rgba(22,163,74,.35); color: #fff; }
|
||||
|
||||
.user-cell { display: flex; align-items: center; gap: 12px; }
|
||||
.avatar {
|
||||
width: 40px; height: 40px; border-radius: 12px;
|
||||
.dash-table { width: 100%; border-collapse: collapse; font-size: .8rem; }
|
||||
.dash-table th {
|
||||
padding: .6rem 1rem; text-align: left;
|
||||
font-size: .67rem; font-weight: 700; text-transform: uppercase;
|
||||
letter-spacing: .06em; color: #6b7f72;
|
||||
background: #f9fafb; border-bottom: 1px solid #f0fdf4;
|
||||
}
|
||||
.dash-table td { padding: .65rem 1rem; border-bottom: 1px solid #f9fafb; color: #374151; vertical-align: middle; }
|
||||
.dash-table tr:last-child td { border-bottom: none; }
|
||||
.dash-table tr:hover td { background: #fafffe; }
|
||||
|
||||
.user-cell { display: flex; align-items: center; gap: .6rem; }
|
||||
.user-avatar {
|
||||
width: 32px; height: 32px; border-radius: 50%; flex-shrink: 0;
|
||||
background: linear-gradient(135deg, #2d7a4f, #38a169);
|
||||
display: flex; align-items: center; justify-content: center;
|
||||
font-size: 0.9rem; font-weight: 800; color: white; flex-shrink: 0;
|
||||
font-size: .72rem; font-weight: 800; color: #fff;
|
||||
}
|
||||
.avatar.super { background: linear-gradient(135deg, #fbbf24, #d97706); }
|
||||
.avatar.admin { background: linear-gradient(135deg, #22c55e, #15803d); }
|
||||
.avatar.user { background: linear-gradient(135deg, #60a5fa, #2563eb); }
|
||||
.user-name { font-size: 0.88rem; font-weight: 700; color: #14532d; }
|
||||
.user-uname { font-size: 0.75rem; color: #86efac; margin-top: 1px; }
|
||||
|
||||
.cell-text { font-size: 0.85rem; color: #4b5563; }
|
||||
.cell-muted { color: #9ca3af; }
|
||||
.user-name { font-weight: 600; color: #111827; font-size: .82rem; }
|
||||
.user-uname { font-size: .7rem; color: #9aada0; }
|
||||
|
||||
.badge {
|
||||
display: inline-flex; align-items: center; gap: 6px;
|
||||
padding: 5px 12px; border-radius: 20px;
|
||||
font-size: 0.72rem; font-weight: 700; letter-spacing: 0.3px;
|
||||
display: inline-flex; align-items: center;
|
||||
padding: .2rem .65rem; border-radius: 999px;
|
||||
font-size: .68rem; font-weight: 700;
|
||||
}
|
||||
.badge-super { background: #fef9c3; color: #854d0e; }
|
||||
.badge-super .dot { background: #ca8a04; }
|
||||
.badge-admin { background: #dcfce7; color: #15803d; }
|
||||
.badge-admin .dot { background: #16a34a; }
|
||||
.badge-user { background: #eff6ff; color: #1d4ed8; }
|
||||
.badge-user .dot { background: #3b82f6; }
|
||||
.badge .dot { width: 6px; height: 6px; border-radius: 50%; }
|
||||
.badge-sa { background: #1a4d2e; color: #fff; }
|
||||
.badge-admin { background: #dcfce7; color: #166534; border: 1px solid #bbf7d0; }
|
||||
.badge-user { background: #f0fdf4; color: #4d7c5a; border: 1px solid #d1fae5; }
|
||||
|
||||
.actions { display: flex; align-items: center; gap: 8px; }
|
||||
.btn-edit {
|
||||
display: inline-flex; align-items: center; gap: 5px;
|
||||
padding: 7px 14px; border-radius: 10px;
|
||||
font-size: 0.78rem; font-weight: 600;
|
||||
background: #dcfce7; color: #15803d;
|
||||
text-decoration: none; transition: all 0.2s ease;
|
||||
border: none; cursor: pointer;
|
||||
display: inline-flex; align-items: center; gap: 4px;
|
||||
padding: .3rem .7rem; border-radius: 7px; font-size: .74rem; font-weight: 600;
|
||||
background: #f0fdf4; color: #166534; border: 1px solid #bbf7d0;
|
||||
text-decoration: none; transition: all .15s; cursor: pointer;
|
||||
}
|
||||
.btn-edit:hover { background: #16a34a; color: white; }
|
||||
.btn-edit:hover { background: #16a34a; color: #fff; border-color: #16a34a; }
|
||||
.btn-delete {
|
||||
display: inline-flex; align-items: center; gap: 5px;
|
||||
padding: 7px 14px; border-radius: 10px;
|
||||
font-size: 0.78rem; font-weight: 600;
|
||||
background: #fef2f2; color: #dc2626;
|
||||
text-decoration: none; transition: all 0.2s ease;
|
||||
border: none; cursor: pointer;
|
||||
display: inline-flex; align-items: center; gap: 4px;
|
||||
padding: .3rem .7rem; border-radius: 7px; font-size: .74rem; font-weight: 600;
|
||||
background: #fef2f2; color: #dc2626; border: 1px solid #fecaca;
|
||||
transition: all .15s; cursor: pointer;
|
||||
}
|
||||
.btn-delete:hover { background: #dc2626; color: white; }
|
||||
.btn-edit svg, .btn-delete svg { width: 13px; height: 13px; }
|
||||
.btn-delete:hover { background: #dc2626; color: #fff; border-color: #dc2626; }
|
||||
|
||||
.empty-state { padding: 60px 20px; text-align: center; }
|
||||
.empty-state svg { width: 56px; height: 56px; color: #bbf7d0; margin: 0 auto 12px; display: block; }
|
||||
.empty-state p { color: #86efac; font-weight: 600; }
|
||||
.row-num { font-size: .75rem; color: #c4d6c8; font-weight: 600; }
|
||||
.cell-muted { color: #c4d6c8; }
|
||||
|
||||
.row-num { font-size: 0.8rem; font-weight: 600; color: #bbf7d0; }
|
||||
.empty-state { padding: 2.5rem; text-align: center; }
|
||||
.empty-state svg { margin: 0 auto .6rem; display: block; }
|
||||
.empty-state p { color: #9aada0; font-size: .82rem; }
|
||||
|
||||
.pagination-wrap { padding: 16px 28px; border-top: 1px solid #dcfce7; }
|
||||
.pagination-wrap { padding: .85rem 1.2rem; border-top: 1px solid #f0fdf4; }
|
||||
</style>
|
||||
|
||||
<div class="users-page">
|
||||
|
||||
@if (session('success'))
|
||||
<div class="alert-success">
|
||||
<svg width="20" height="20" 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 style="font-weight:600; font-size:0.9rem;">{{ session('success') }}</span>
|
||||
@if(session('success'))
|
||||
<div class="alert alert-success">
|
||||
<svg width="15" height="15" 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>
|
||||
{{ session('success') }}
|
||||
</div>
|
||||
@endif
|
||||
@if (session('error'))
|
||||
<div class="alert-error">
|
||||
<svg width="20" height="20" fill="currentColor" viewBox="0 0 20 20"><path fill-rule="evenodd" d="M18 10a8 8 0 11-16 0 8 8 0 0116 0zm-7 4a1 1 0 11-2 0 1 1 0 012 0zm-1-9a1 1 0 00-1 1v4a1 1 0 102 0V6a1 1 0 00-1-1z" clip-rule="evenodd"/></svg>
|
||||
<span style="font-weight:600; font-size:0.9rem;">{{ session('error') }}</span>
|
||||
@if(session('error'))
|
||||
<div class="alert alert-error">
|
||||
<svg width="15" height="15" fill="currentColor" viewBox="0 0 20 20"><path fill-rule="evenodd" d="M18 10a8 8 0 11-16 0 8 8 0 0116 0zm-7 4a1 1 0 11-2 0 1 1 0 012 0zm-1-9a1 1 0 00-1 1v4a1 1 0 102 0V6a1 1 0 00-1-1z" clip-rule="evenodd"/></svg>
|
||||
{{ session('error') }}
|
||||
</div>
|
||||
@endif
|
||||
|
||||
<div class="table-card">
|
||||
<div class="table-card-header">
|
||||
<div class="table-card-header-left">
|
||||
<div class="header-dot"></div>
|
||||
<h3>Daftar Pengguna</h3>
|
||||
<div class="table-card-hdr">
|
||||
<div class="table-card-hdr-left">
|
||||
<span class="table-card-title">Daftar Pengguna</span>
|
||||
<span class="count-badge">{{ $users->total() }} total</span>
|
||||
</div>
|
||||
<a href="{{ route('super-admin.users.create') }}" class="btn-add">
|
||||
<svg fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2.5" d="M12 4v16m8-8H4"/></svg>
|
||||
<svg width="12" height="12" fill="none" stroke="currentColor" viewBox="0 0 24 24" stroke-width="2.5"><path stroke-linecap="round" stroke-linejoin="round" d="M12 4v16m8-8H4"/></svg>
|
||||
Tambah Pengguna
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div style="overflow-x:auto;">
|
||||
<table>
|
||||
<table class="dash-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>#</th>
|
||||
|
|
@ -180,48 +135,40 @@
|
|||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@forelse ($users as $user)
|
||||
@forelse($users as $user)
|
||||
<tr>
|
||||
<td><span class="row-num">{{ $loop->iteration }}</span></td>
|
||||
<td>
|
||||
<div class="user-cell">
|
||||
<div class="avatar {{ $user->role === 'super_admin' ? 'super' : ($user->role === 'admin' ? 'admin' : 'user') }}">
|
||||
{{ strtoupper(substr($user->nama, 0, 1)) }}
|
||||
</div>
|
||||
<div class="user-avatar">{{ strtoupper(substr($user->nama, 0, 1)) }}</div>
|
||||
<div>
|
||||
<div class="user-name">{{ $user->nama }}</div>
|
||||
<div class="user-uname">{{ $user->username }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
<td><span class="cell-text">{{ $user->email }}</span></td>
|
||||
<td><span class="cell-text {{ !$user->no_hp ? 'cell-muted' : '' }}">{{ $user->no_hp ?? '—' }}</span></td>
|
||||
<td style="color:#6b7280;">{{ $user->email }}</td>
|
||||
<td><span class="{{ !$user->no_hp ? 'cell-muted' : '' }}">{{ $user->no_hp ?? '—' }}</span></td>
|
||||
<td>
|
||||
@if($user->role === 'super_admin')
|
||||
<span class="px-3 py-1 inline-flex text-xs leading-5 font-bold rounded-full bg-gradient-to-r from-yellow-500 to-yellow-600 text-white shadow-md">
|
||||
⭐ Super Admin
|
||||
</span>
|
||||
<span class="badge badge-sa">Super Admin</span>
|
||||
@elseif($user->role === 'admin')
|
||||
<span class="px-3 py-1 inline-flex text-xs leading-5 font-bold rounded-full bg-gradient-to-r from-green-500 to-green-600 text-white shadow-md">
|
||||
👤 Admin
|
||||
</span>
|
||||
<span class="badge badge-admin">Admin</span>
|
||||
@else
|
||||
<span class="px-3 py-1 inline-flex text-xs leading-5 font-bold rounded-full bg-gradient-to-r from-blue-400 to-blue-500 text-white shadow-md">
|
||||
👥 User
|
||||
</span>
|
||||
<span class="badge badge-user">User</span>
|
||||
@endif
|
||||
</td>
|
||||
<td>
|
||||
<div class="actions">
|
||||
<div style="display:flex;align-items:center;gap:.4rem;">
|
||||
<a href="{{ route('super-admin.users.edit', $user) }}" class="btn-edit">
|
||||
<svg 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"/></svg>
|
||||
<svg width="11" height="11" fill="none" stroke="currentColor" viewBox="0 0 24 24" stroke-width="2"><path stroke-linecap="round" stroke-linejoin="round" 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"/></svg>
|
||||
Edit
|
||||
</a>
|
||||
@if($user->id !== auth()->id())
|
||||
<form action="{{ route('super-admin.users.destroy', $user) }}" method="POST" style="display:inline;" onsubmit="return confirm('Yakin ingin menghapus {{ $user->nama }}?')">
|
||||
<form action="{{ route('super-admin.users.destroy', $user) }}" method="POST" style="display:inline;" onsubmit="return confirm('Yakin hapus {{ $user->nama }}?')">
|
||||
@csrf @method('DELETE')
|
||||
<button type="submit" class="btn-delete">
|
||||
<svg fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16"/></svg>
|
||||
<svg width="11" height="11" fill="none" stroke="currentColor" viewBox="0 0 24 24" stroke-width="2"><path stroke-linecap="round" stroke-linejoin="round" d="M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16"/></svg>
|
||||
Hapus
|
||||
</button>
|
||||
</form>
|
||||
|
|
@ -233,7 +180,7 @@
|
|||
<tr>
|
||||
<td colspan="6">
|
||||
<div class="empty-state">
|
||||
<svg fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M17 20h5v-2a3 3 0 00-5.356-1.857M17 20H7m10 0v-2c0-.656-.126-1.283-.356-1.857M7 20H2v-2a3 3 0 015.356-1.857M7 20v-2c0-.656.126-1.283.356-1.857m0 0a5.002 5.002 0 019.288 0M15 7a3 3 0 11-6 0 3 3 0 016 0z"/></svg>
|
||||
<svg width="36" height="36" fill="none" stroke="#c4d6c8" viewBox="0 0 24 24" stroke-width="1.5"><path stroke-linecap="round" stroke-linejoin="round" d="M17 20h5v-2a3 3 0 00-5.356-1.857M17 20H7m10 0v-2c0-.656-.126-1.283-.356-1.857M7 20H2v-2a3 3 0 015.356-1.857M7 20v-2c0-.656.126-1.283.356-1.857m0 0a5.002 5.002 0 019.288 0M15 7a3 3 0 11-6 0 3 3 0 016 0z"/></svg>
|
||||
<p>Belum ada data pengguna</p>
|
||||
</div>
|
||||
</td>
|
||||
|
|
|
|||
|
|
@ -3,280 +3,326 @@
|
|||
@section('page-title', 'Hasil Diagnosa')
|
||||
|
||||
@push('styles')
|
||||
<link href="https://fonts.googleapis.com/css2?family=Plus+Jakarta+Sans:wght@400;500;600;700;800&family=DM+Mono:wght@400;500&display=swap" rel="stylesheet">
|
||||
<link href="https://fonts.googleapis.com/css2?family=Sora:wght@300;400;500;600;700;800&family=Instrument+Serif:ital@0;1&family=JetBrains+Mono:wght@400;500&display=swap" rel="stylesheet">
|
||||
<style>
|
||||
:root {
|
||||
--green-deep: #1a4d2e;
|
||||
--green-mid: #2d7a4f;
|
||||
--green-bright:#4ade80;
|
||||
--green-bright: #4ade80;
|
||||
--bg-base: #f0f5f1;
|
||||
--bg-card: #ffffff;
|
||||
--text-primary:#0f1f14;
|
||||
--text-primary: #0f1f14;
|
||||
--text-muted: #6b7f72;
|
||||
--shadow: 0 4px 24px rgba(29,77,46,.08), 0 1px 4px rgba(29,77,46,.05);
|
||||
--shadow-deep: 0 8px 40px rgba(29,77,46,.16), 0 2px 8px rgba(29,77,46,.08);
|
||||
--radius: 20px;
|
||||
--r-sm: 10px;
|
||||
--r-md: 16px;
|
||||
--r-lg: 20px;
|
||||
--r-xl: 20px;
|
||||
--white: #ffffff;
|
||||
--ink: #0f1f14;
|
||||
--smoke: #6b7f72;
|
||||
--fog: #9aada0;
|
||||
--parchment:#f0f5f1;
|
||||
--mist: #dcfce7;
|
||||
--leaf: #16a34a;
|
||||
--leaf-mid: #2d7a4f;
|
||||
}
|
||||
body, .hasil-root { font-family: 'Plus Jakarta Sans', sans-serif; background: var(--bg-base); }
|
||||
|
||||
@keyframes fadeUp {
|
||||
from { opacity:0; transform:translateY(14px); }
|
||||
to { opacity:1; transform:translateY(0); }
|
||||
}
|
||||
.a1 { animation: fadeUp .5s cubic-bezier(.22,1,.36,1) .04s both; }
|
||||
.a2 { animation: fadeUp .5s cubic-bezier(.22,1,.36,1) .12s both; }
|
||||
.a3 { animation: fadeUp .5s cubic-bezier(.22,1,.36,1) .20s both; }
|
||||
.a4 { animation: fadeUp .5s cubic-bezier(.22,1,.36,1) .28s both; }
|
||||
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
|
||||
body, .hasil-root { font-family: 'Sora', sans-serif; background: var(--bg-base); color: var(--text-primary); }
|
||||
|
||||
/* ─── Page header ─── */
|
||||
.page-hdr {
|
||||
display:flex; align-items:center; justify-content:space-between;
|
||||
margin-bottom:1.5rem; flex-wrap:wrap; gap:.75rem;
|
||||
}
|
||||
.page-hdr-title { font-size:1.5rem; font-weight:800; color:var(--text-primary); letter-spacing:-.03em; }
|
||||
.btn-dl {
|
||||
display:inline-flex; align-items:center; gap:.5rem;
|
||||
padding:.55rem 1.2rem;
|
||||
background:rgba(255,255,255,.15); border:1.5px solid rgba(255,255,255,.35);
|
||||
color:#fff; font-size:.8rem; font-weight:700;
|
||||
border-radius:50px; text-decoration:none;
|
||||
transition:all .2s;
|
||||
}
|
||||
.btn-dl:hover { background:rgba(255,255,255,.25); border-color:rgba(255,255,255,.6); transform:translateY(-1px); }
|
||||
/* ── Animations ── */
|
||||
@keyframes slideUp { from { opacity:0; transform:translateY(18px); } to { opacity:1; transform:translateY(0); } }
|
||||
@keyframes scaleIn { from { opacity:0; transform:scale(.97); } to { opacity:1; transform:scale(1); } }
|
||||
@keyframes fillBar { from { width:0%; } to { width:var(--w); } }
|
||||
@keyframes pulse-glow { 0%,100% { box-shadow:0 0 0 0 rgba(106,173,94,.35); } 50% { box-shadow:0 0 0 8px rgba(106,173,94,0); } }
|
||||
|
||||
/* ─── Disease banner ─── */
|
||||
.a1 { animation: scaleIn .55s cubic-bezier(.16,1,.3,1) .05s both; }
|
||||
.a2 { animation: slideUp .5s cubic-bezier(.16,1,.3,1) .15s both; }
|
||||
.a3 { animation: slideUp .5s cubic-bezier(.16,1,.3,1) .25s both; }
|
||||
.a4 { animation: slideUp .5s cubic-bezier(.16,1,.3,1) .35s both; }
|
||||
|
||||
/* ── Hero Banner ── */
|
||||
.banner {
|
||||
position: relative; overflow: hidden;
|
||||
border-radius: var(--r-xl);
|
||||
margin-bottom: 1.5rem;
|
||||
background: linear-gradient(130deg, #1a4d2e 0%, #2d7a4f 58%, #38a169 100%);
|
||||
border-radius: var(--radius); padding:1.75rem 2rem;
|
||||
color:#fff; position:relative; overflow:hidden;
|
||||
margin-bottom:1.25rem;
|
||||
box-shadow:0 8px 32px rgba(26,77,46,.28);
|
||||
box-shadow: 0 8px 32px rgba(26,77,46,.28);
|
||||
}
|
||||
.banner::before {
|
||||
content:''; position:absolute; inset:0;
|
||||
.banner-texture {
|
||||
position: absolute; inset: 0; pointer-events: none;
|
||||
background-image:
|
||||
linear-gradient(rgba(255,255,255,.04) 1px, transparent 1px),
|
||||
linear-gradient(90deg, rgba(255,255,255,.04) 1px, transparent 1px);
|
||||
background-size:28px 28px; pointer-events:none;
|
||||
background-size: 28px 28px;
|
||||
}
|
||||
.banner::after {
|
||||
content:''; position:absolute; top:-80px; right:-60px;
|
||||
width:240px; height:240px; border-radius:50%;
|
||||
background:radial-gradient(circle, rgba(74,222,128,.18) 0%, transparent 70%);
|
||||
pointer-events:none;
|
||||
.banner-stripe {
|
||||
position: absolute; top: -80px; right: -60px;
|
||||
width: 240px; height: 240px; border-radius: 50%;
|
||||
background: radial-gradient(circle, rgba(74,222,128,.18) 0%, transparent 70%);
|
||||
pointer-events: none;
|
||||
}
|
||||
.banner-in { position:relative; z-index:1; }
|
||||
.banner-inner { position: relative; z-index: 1; padding: 2rem 2.25rem; }
|
||||
|
||||
.banner-toprow { display:flex; align-items:flex-start; justify-content:space-between; gap:1rem; flex-wrap:wrap; margin-bottom:.9rem; }
|
||||
/* Banner top row */
|
||||
.banner-toprow { display: flex; align-items: flex-start; justify-content: space-between; gap: 1.25rem; flex-wrap: wrap; margin-bottom: 1.25rem; }
|
||||
|
||||
/* Pills */
|
||||
.pill-row { display: flex; gap: .5rem; flex-wrap: wrap; margin-bottom: .85rem; }
|
||||
.pill {
|
||||
display:inline-flex; align-items:center; gap:.35rem;
|
||||
padding:.28rem .85rem; border-radius:50px;
|
||||
font-size:.68rem; font-weight:700; letter-spacing:.06em; text-transform:uppercase;
|
||||
display: inline-flex; align-items: center; gap: .3rem;
|
||||
padding: .3rem .85rem; border-radius: 999px;
|
||||
font-size: .68rem; font-weight: 600; letter-spacing: .07em; text-transform: uppercase;
|
||||
}
|
||||
.pill-detected { background:rgba(255,255,255,.15); border:1px solid rgba(255,255,255,.25); color:#fff; }
|
||||
.pill-danger-st { background:#dc2626; color:#fff; }
|
||||
.pill-danger-t { background:#f97316; color:#fff; }
|
||||
.pill-danger-s { background:#fde047; color:#713f12; }
|
||||
.pill-danger-r { background:#bbf7d0; color:#14532d; }
|
||||
.pill-detected { background: rgba(255,255,255,.12); border: 1px solid rgba(255,255,255,.2); color: rgba(255,255,255,.9); }
|
||||
.pill-st { background: #dc2626; color: #fff; }
|
||||
.pill-t { background: #ea580c; color: #fff; }
|
||||
.pill-s { background: #ca8a04; color: #fff; }
|
||||
.pill-r { background: rgba(106,173,94,.25); border: 1px solid rgba(106,173,94,.4); color: #a3e09a; }
|
||||
|
||||
.disease-name { font-size:1.6rem; font-weight:800; letter-spacing:-.03em; line-height:1.2; }
|
||||
.disease-latin { font-style:italic; font-size:.8rem; color:rgba(255,255,255,.6); margin-top:.25rem; }
|
||||
.date-meta { text-align:right; font-size:.72rem; color:rgba(255,255,255,.5); font-family:'DM Mono',monospace; flex-shrink:0; }
|
||||
.date-meta small { display:block; font-size:.62rem; color:rgba(255,255,255,.3); margin-top:.35rem; }
|
||||
/* Disease name */
|
||||
.disease-block {}
|
||||
.disease-name { font-family: 'Instrument Serif', serif; font-size: 2.1rem; line-height: 1.15; color: #fff; letter-spacing: -.01em; }
|
||||
.disease-latin { font-family: 'Instrument Serif', serif; font-style: italic; font-size: .95rem; color: rgba(255,255,255,.45); margin-top: .3rem; }
|
||||
|
||||
.cf-box { background:rgba(0,0,0,.18); border-radius:14px; padding:.95rem 1.2rem; margin-top:.75rem; }
|
||||
.cf-row { display:flex; align-items:center; justify-content:space-between; margin-bottom:.55rem; }
|
||||
.cf-lbl { font-size:.76rem; font-weight:600; color:rgba(255,255,255,.8); }
|
||||
.cf-val { font-size:2rem; font-weight:800; letter-spacing:-.04em; }
|
||||
.cf-track { background:rgba(0,0,0,.25); border-radius:999px; height:10px; }
|
||||
.cf-fill { background:#fff; border-radius:999px; height:10px; }
|
||||
.cf-ticks { display:flex; justify-content:space-between; font-size:.63rem; color:rgba(255,255,255,.4); margin-top:.3rem; }
|
||||
/* Date meta */
|
||||
.date-meta { text-align: right; flex-shrink: 0; }
|
||||
.date-meta .date-big { font-size: .85rem; color: rgba(255,255,255,.7); font-weight: 500; }
|
||||
.date-meta .date-time { font-size: .75rem; color: rgba(255,255,255,.4); margin-top: .2rem; }
|
||||
.date-meta .date-id { font-family: 'JetBrains Mono', monospace; font-size: .65rem; color: rgba(255,255,255,.25); margin-top: .5rem; }
|
||||
|
||||
/* ─── Two-column layout ─── */
|
||||
/* Wireframe: left = narrow (label column), right = wide (content) */
|
||||
.main-grid {
|
||||
display:grid;
|
||||
grid-template-columns: 220px 1fr;
|
||||
gap:1.25rem;
|
||||
align-items:start;
|
||||
/* CF bar */
|
||||
.cf-panel {
|
||||
background: rgba(0,0,0,.25); border-radius: var(--r-md);
|
||||
padding: 1.1rem 1.4rem; backdrop-filter: blur(4px);
|
||||
border: 1px solid rgba(255,255,255,.07);
|
||||
}
|
||||
@media (max-width:900px) { .main-grid { grid-template-columns:1fr; } }
|
||||
.cf-header { display: flex; align-items: center; justify-content: space-between; margin-bottom: .75rem; }
|
||||
.cf-label { font-size: .72rem; font-weight: 600; color: rgba(255,255,255,.55); letter-spacing: .05em; text-transform: uppercase; }
|
||||
.cf-value { font-family: 'Instrument Serif', serif; font-size: 2.4rem; color: #fff; line-height: 1; }
|
||||
.cf-track { background: rgba(0,0,0,.3); border-radius: 999px; height: 8px; overflow: hidden; }
|
||||
.cf-fill { height: 8px; border-radius: 999px; background: #ffffff; }
|
||||
.cf-ticks { display: flex; justify-content: space-between; font-size: .62rem; color: rgba(255,255,255,.3); margin-top: .4rem; font-family: 'JetBrains Mono', monospace; }
|
||||
|
||||
/* ─── Card ─── */
|
||||
/* Disease image inside banner */
|
||||
.banner-img-wrap {
|
||||
margin-top: 1.1rem; border-radius: var(--r-md); overflow: hidden;
|
||||
aspect-ratio: 21/7; background: rgba(0,0,0,.2);
|
||||
border: 1px solid rgba(255,255,255,.1);
|
||||
}
|
||||
.banner-img-wrap img { width: 100%; height: 100%; object-fit: cover; display: block; opacity: .85; }
|
||||
|
||||
/* Download button */
|
||||
.btn-dl {
|
||||
display: inline-flex; align-items: center; gap: .5rem;
|
||||
padding: .55rem 1.2rem; border-radius: 50px;
|
||||
background: rgba(255,255,255,.15); border: 1.5px solid rgba(255,255,255,.35);
|
||||
color: #fff; font-size: .8rem; font-weight: 700; text-decoration: none;
|
||||
margin-top: .85rem; transition: all .2s;
|
||||
}
|
||||
.btn-dl:hover { background: rgba(255,255,255,.25); border-color: rgba(255,255,255,.6); transform: translateY(-1px); }
|
||||
|
||||
/* ── Layout ── */
|
||||
.main-grid { display: grid; grid-template-columns: 230px 1fr; gap: 1.25rem; align-items: start; }
|
||||
@media (max-width: 860px) { .main-grid { grid-template-columns: 1fr; } }
|
||||
.col-stack { display: flex; flex-direction: column; gap: 1.25rem; }
|
||||
|
||||
/* ── Card ── */
|
||||
.card {
|
||||
background:var(--bg-card); border-radius:var(--radius);
|
||||
border:1.5px solid rgba(29,77,46,.07);
|
||||
box-shadow:var(--shadow); overflow:hidden;
|
||||
transition:transform .2s, box-shadow .2s;
|
||||
background: var(--bg-card); border-radius: var(--radius);
|
||||
border: 1.5px solid rgba(29,77,46,.07);
|
||||
box-shadow: var(--shadow); overflow: hidden;
|
||||
transition: transform .2s, box-shadow .2s;
|
||||
}
|
||||
.card:hover { transform:translateY(-2px); box-shadow:0 8px 28px rgba(29,77,46,.12); }
|
||||
.card:hover { transform: translateY(-2px); box-shadow: 0 8px 28px rgba(29,77,46,.12); }
|
||||
|
||||
.card-hdr {
|
||||
display:flex; align-items:center; gap:.6rem;
|
||||
padding:.9rem 1.2rem;
|
||||
border-bottom:1px solid rgba(29,77,46,.07);
|
||||
display: flex; align-items: center; gap: .6rem;
|
||||
padding: .9rem 1.2rem; border-bottom: 1px solid rgba(29,77,46,.07);
|
||||
}
|
||||
.card-hdr-icon {
|
||||
width:30px; height:30px; border-radius:8px; flex-shrink:0;
|
||||
display:flex; align-items:center; justify-content:center;
|
||||
width: 30px; height: 30px; border-radius: 8px; flex-shrink: 0;
|
||||
display: flex; align-items: center; justify-content: center;
|
||||
}
|
||||
.card-hdr-title { font-size:.85rem; font-weight:700; color:var(--text-primary); letter-spacing:-.01em; }
|
||||
.card-body { padding:1.1rem 1.2rem; }
|
||||
.card-hdr-title { font-size: .85rem; font-weight: 700; color: var(--text-primary); letter-spacing: -.01em; }
|
||||
.card-body { padding: 1.1rem 1.2rem; }
|
||||
|
||||
/* ─── Info table rows ─── */
|
||||
.info-row { display:flex; justify-content:space-between; align-items:center; padding:.55rem 0; border-bottom:1px solid rgba(29,77,46,.06); font-size:.78rem; }
|
||||
.info-row:last-child { border-bottom:none; }
|
||||
.info-k { color:var(--text-muted); font-weight:500; }
|
||||
.info-v { font-weight:700; color:var(--text-primary); }
|
||||
.info-v.green { color:#16a34a; }
|
||||
.info-v.blue { color:#2563eb; }
|
||||
/* ── Info rows ── */
|
||||
.info-row { display: flex; justify-content: space-between; align-items: center; padding: .55rem 0; border-bottom: 1px solid rgba(29,77,46,.06); font-size: .78rem; }
|
||||
.info-row:last-child { border-bottom: none; }
|
||||
.info-k { color: var(--text-muted); font-weight: 500; }
|
||||
.info-v { font-weight: 700; color: var(--text-primary); }
|
||||
.info-v.leaf { color: #16a34a; }
|
||||
.info-v.blue { color: #2563eb; }
|
||||
|
||||
/* ─── Gejala ─── */
|
||||
.gejala-item {
|
||||
display:flex; align-items:flex-start; gap:.45rem;
|
||||
padding:.45rem .6rem; background:#f0fdf4;
|
||||
border-radius:8px; font-size:.76rem; color:#166534;
|
||||
font-weight:500; margin-bottom:.38rem;
|
||||
/* ── Gejala chips ── */
|
||||
.gejala-wrap { display: flex; flex-direction: column; gap: .38rem; }
|
||||
.gejala-chip {
|
||||
display: flex; align-items: flex-start; gap: .45rem;
|
||||
padding: .45rem .6rem; background: #f0fdf4;
|
||||
border-radius: 8px; font-size: .76rem; color: #166534;
|
||||
font-weight: 500; line-height: 1.45;
|
||||
}
|
||||
.gejala-item svg { flex-shrink:0; margin-top:1px; }
|
||||
.gejala-chip svg { flex-shrink: 0; margin-top: 1px; }
|
||||
|
||||
/* ─── Desc ─── */
|
||||
.desc-box { background:#f9fafb; border-radius:12px; padding:.9rem 1rem; font-size:.8rem; color:#4b5563; line-height:1.65; }
|
||||
/* ── Description ── */
|
||||
.desc-box { background: #f9fafb; border-radius: 12px; padding: .9rem 1rem; font-size: .8rem; color: #4b5563; line-height: 1.65; }
|
||||
|
||||
/* ─── Pengendalian ─── */
|
||||
.ctrl-grid { display:grid; grid-template-columns:1fr 1fr; gap:.65rem; }
|
||||
@media (max-width:600px) { .ctrl-grid { grid-template-columns:1fr; } }
|
||||
.ctrl-card { border-radius:13px; padding:.9rem; font-size:.76rem; line-height:1.6; border:1.5px solid transparent; }
|
||||
.ctrl-lbl { display:flex; align-items:center; gap:.4rem; font-size:.73rem; font-weight:700; margin-bottom:.45rem; }
|
||||
.ctrl-lbl-icon { width:24px; height:24px; border-radius:6px; display:flex; align-items:center; justify-content:center; flex-shrink:0; }
|
||||
/* ── Pengendalian grid ── */
|
||||
.ctrl-grid { display: grid; grid-template-columns: 1fr 1fr; gap: .65rem; }
|
||||
@media (max-width: 560px) { .ctrl-grid { grid-template-columns: 1fr; } }
|
||||
.ctrl-card { border-radius: 13px; padding: .9rem; font-size: .76rem; line-height: 1.6; border: 1.5px solid transparent; }
|
||||
.ctrl-lbl { display: flex; align-items: center; gap: .4rem; font-size: .73rem; font-weight: 700; margin-bottom: .45rem; }
|
||||
.ctrl-lbl-icon { width: 24px; height: 24px; border-radius: 6px; display: flex; align-items: center; justify-content: center; flex-shrink: 0; }
|
||||
|
||||
.ctrl-pencegahan { background:#eff6ff; border-color:#dbeafe; color:#1e40af; }
|
||||
.ctrl-pencegahan .ctrl-lbl { color:#1e40af; } .ctrl-pencegahan .ctrl-lbl-icon { background:#dbeafe; }
|
||||
.ctrl-kimia { background:#fff7ed; border-color:#fed7aa; color:#c2410c; }
|
||||
.ctrl-kimia .ctrl-lbl { color:#c2410c; } .ctrl-kimia .ctrl-lbl-icon { background:#fed7aa; }
|
||||
.ctrl-organik { background:#f0fdf4; border-color:#bbf7d0; color:#15803d; }
|
||||
.ctrl-organik .ctrl-lbl { color:#15803d; } .ctrl-organik .ctrl-lbl-icon { background:#bbf7d0; }
|
||||
.ctrl-budidaya { background:#fefce8; border-color:#fde68a; color:#a16207; }
|
||||
.ctrl-budidaya .ctrl-lbl { color:#a16207; } .ctrl-budidaya .ctrl-lbl-icon { background:#fde68a; }
|
||||
.ctrl-pencegahan { background: #eff6ff; border-color: #dbeafe; color: #1e40af; }
|
||||
.ctrl-pencegahan .ctrl-lbl { color: #1e40af; } .ctrl-pencegahan .ctrl-lbl-icon { background: #dbeafe; }
|
||||
.ctrl-kimia { background: #fff7ed; border-color: #fed7aa; color: #c2410c; }
|
||||
.ctrl-kimia .ctrl-lbl { color: #c2410c; } .ctrl-kimia .ctrl-lbl-icon { background: #fed7aa; }
|
||||
.ctrl-organik { background: #f0fdf4; border-color: #bbf7d0; color: #15803d; }
|
||||
.ctrl-organik .ctrl-lbl { color: #15803d; } .ctrl-organik .ctrl-lbl-icon { background: #bbf7d0; }
|
||||
.ctrl-budidaya { background: #fefce8; border-color: #fde68a; color: #a16207; }
|
||||
.ctrl-budidaya .ctrl-lbl { color: #a16207; } .ctrl-budidaya .ctrl-lbl-icon { background: #fde68a; }
|
||||
|
||||
/* ─── Kemungkinan ─── */
|
||||
.kemung-item { display:flex; align-items:center; gap:.7rem; padding:.7rem; border-radius:12px; margin-bottom:.45rem; }
|
||||
.kemung-item.r1 { background:#f0fdf4; border:1.5px solid #bbf7d0; }
|
||||
.kemung-item.rother{ background:#f9fafb; border:1px solid #f3f4f6; }
|
||||
.rank-circle { width:26px; height:26px; border-radius:50%; font-size:.72rem; font-weight:800; display:flex; align-items:center; justify-content:center; flex-shrink:0; }
|
||||
.rc-1 { background:#16a34a; color:#fff; }
|
||||
.rc-other{ background:#e5e7eb; color:#6b7280; }
|
||||
.bar-track { flex:1; background:#e5e7eb; border-radius:999px; height:6px; }
|
||||
.bar-fill { border-radius:999px; height:6px; }
|
||||
/* ── Kemungkinan list ── */
|
||||
.kemung-list { display: flex; flex-direction: column; gap: .45rem; }
|
||||
.kemung-item { display: flex; align-items: center; gap: .7rem; padding: .7rem; border-radius: 12px; }
|
||||
.kemung-item.top { background: #f0fdf4; border: 1.5px solid #bbf7d0; }
|
||||
.kemung-item.rest { background: #f9fafb; border: 1px solid #f3f4f6; }
|
||||
.rank-num { width: 26px; height: 26px; border-radius: 50%; font-size: .72rem; font-weight: 800; display: flex; align-items: center; justify-content: center; flex-shrink: 0; }
|
||||
.rank-num.r1 { background: #16a34a; color: #fff; }
|
||||
.rank-num.ro { background: #e5e7eb; color: #6b7280; }
|
||||
.kemung-name { font-size: .8rem; font-weight: 500; color: #374151; }
|
||||
.kemung-name.top { font-weight: 700; color: #166534; }
|
||||
.bar-wrap { flex-shrink: 0; width: 80px; height: 6px; background: #e5e7eb; border-radius: 999px; overflow: hidden; }
|
||||
.bar-fill-k { height: 6px; border-radius: 999px; }
|
||||
.kemung-pct { font-size: .8rem; font-weight: 800; flex-shrink: 0; width: 38px; text-align: right; }
|
||||
|
||||
/* ─── Action buttons ─── */
|
||||
.btn-main {
|
||||
display:flex; align-items:center; justify-content:center; gap:.5rem;
|
||||
padding:.7rem 1rem; background:linear-gradient(135deg, #2d7a4f, #16a34a);
|
||||
color:#fff; font-weight:700; font-size:.82rem; border-radius:13px;
|
||||
text-decoration:none; width:100%;
|
||||
box-shadow:0 4px 14px rgba(22,163,74,.3); transition:all .2s;
|
||||
/* ── Action buttons ── */
|
||||
.btn-primary {
|
||||
display: flex; align-items: center; justify-content: center; gap: .5rem;
|
||||
padding: .7rem 1rem; border-radius: 13px; width: 100%; text-decoration: none;
|
||||
background: linear-gradient(135deg, #2d7a4f, #16a34a);
|
||||
color: #fff; font-weight: 700; font-size: .82rem;
|
||||
box-shadow: 0 4px 14px rgba(22,163,74,.3); transition: all .2s;
|
||||
}
|
||||
.btn-main:hover { transform:translateY(-2px); box-shadow:0 6px 20px rgba(22,163,74,.4); }
|
||||
.btn-sec {
|
||||
display:flex; align-items:center; justify-content:center; gap:.5rem;
|
||||
padding:.7rem 1rem; background:var(--bg-card); color:var(--text-primary);
|
||||
font-weight:600; font-size:.82rem; border-radius:13px;
|
||||
text-decoration:none; width:100%; border:1.5px solid rgba(29,77,46,.15); transition:all .2s;
|
||||
.btn-primary:hover { transform: translateY(-2px); box-shadow: 0 6px 20px rgba(22,163,74,.4); }
|
||||
.btn-secondary {
|
||||
display: flex; align-items: center; justify-content: center; gap: .5rem;
|
||||
padding: .7rem 1rem; border-radius: 13px; width: 100%; text-decoration: none;
|
||||
background: var(--bg-card); color: var(--text-primary);
|
||||
font-weight: 600; font-size: .82rem;
|
||||
border: 1.5px solid rgba(29,77,46,.15); transition: all .2s;
|
||||
}
|
||||
.btn-sec:hover { background:#f0fdf4; transform:translateY(-1px); }
|
||||
.btn-secondary:hover { background: #f0fdf4; transform: translateY(-1px); }
|
||||
|
||||
/* ─── Relasi table ─── */
|
||||
.relasi-wrap { overflow-x:auto; }
|
||||
.relasi-table { width:100%; border-collapse:collapse; font-size:.76rem; }
|
||||
.relasi-table th { padding:.6rem .8rem; text-align:left; font-weight:700; font-size:.67rem; text-transform:uppercase; letter-spacing:.06em; color:var(--text-muted); background:#f9fafb; border-bottom:1px solid #e5e7eb; }
|
||||
.relasi-table th:not(:first-child) { text-align:center; }
|
||||
.relasi-table td { padding:.55rem .8rem; border-bottom:1px solid #f3f4f6; color:#374151; }
|
||||
.relasi-table td:not(:first-child) { text-align:center; }
|
||||
.relasi-table tr:last-child td { border-bottom:none; }
|
||||
.relasi-table tr:hover td { background:#f9fafb; }
|
||||
.chk-yes { display:inline-flex; align-items:center; justify-content:center; width:24px; height:24px; background:#dcfce7; border-radius:50%; }
|
||||
.chk-no { display:inline-flex; align-items:center; justify-content:center; width:24px; height:24px; background:#f3f4f6; border-radius:50%; }
|
||||
/* ── Relasi table ── */
|
||||
.relasi-outer { overflow-x: auto; -webkit-overflow-scrolling: touch; }
|
||||
.relasi-table { width: 100%; border-collapse: collapse; font-size: .76rem; }
|
||||
.relasi-table th { padding: .6rem .8rem; text-align: left; font-weight: 700; font-size: .67rem; text-transform: uppercase; letter-spacing: .06em; color: var(--text-muted); background: #f9fafb; border-bottom: 1px solid #e5e7eb; }
|
||||
.relasi-table th:not(:first-child) { text-align: center; }
|
||||
.relasi-table td { padding: .55rem .8rem; border-bottom: 1px solid #f3f4f6; color: #374151; }
|
||||
.relasi-table td:not(:first-child) { text-align: center; }
|
||||
.relasi-table tr:last-child td { border-bottom: none; }
|
||||
.relasi-table tr:hover td { background: #f9fafb; }
|
||||
.chk-yes { display: inline-flex; align-items: center; justify-content: center; width: 24px; height: 24px; background: #dcfce7; border-radius: 50%; }
|
||||
.chk-no { display: inline-flex; align-items: center; justify-content: center; width: 24px; height: 24px; background: #f3f4f6; border-radius: 50%; }
|
||||
.relasi-legend { font-size: .68px; color: #9ca3af; padding: .65rem 1.2rem; border-top: 1px solid #f3f4f6; }
|
||||
|
||||
.col-stack { display:flex; flex-direction:column; gap:1.25rem; }
|
||||
/* ── Image card ── */
|
||||
.img-card-img { width: 100%; aspect-ratio: 4/3; object-fit: cover; display: block; border-radius: 12px 12px 0 0; }
|
||||
.img-card-caption { font-size: .68rem; color: var(--text-muted); text-align: center; padding: .5rem; font-style: italic; border-top: 1px solid rgba(29,77,46,.07); }
|
||||
</style>
|
||||
@endpush
|
||||
|
||||
@section('content')
|
||||
<div class="hasil-root">
|
||||
|
||||
{{-- Disease banner --}}
|
||||
{{-- ── Hero Banner ── --}}
|
||||
<div class="banner a1">
|
||||
<div class="banner-in">
|
||||
<div class="banner-texture"></div>
|
||||
<div class="banner-stripe"></div>
|
||||
<div class="banner-inner">
|
||||
|
||||
<div class="banner-toprow">
|
||||
<div>
|
||||
<div style="display:flex;gap:.45rem;flex-wrap:wrap;margin-bottom:.7rem;">
|
||||
<div class="disease-block" style="flex:1; min-width:0;">
|
||||
<div class="pill-row">
|
||||
<span class="pill pill-detected">
|
||||
<svg width="10" height="10" fill="none" stroke="currentColor" viewBox="0 0 24 24" stroke-width="2.5"><path stroke-linecap="round" stroke-linejoin="round" d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z"/></svg>
|
||||
Penyakit Terdeteksi
|
||||
<svg width="9" height="9" fill="none" stroke="currentColor" viewBox="0 0 24 24" stroke-width="2.5"><path stroke-linecap="round" stroke-linejoin="round" d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z"/></svg>
|
||||
{{ ($riwayat->penyakit?->kategori === 'Hama') ? 'Hama Terdeteksi' : 'Penyakit Terdeteksi' }}
|
||||
</span>
|
||||
@if($riwayat->penyakit?->tingkat_bahaya)
|
||||
@php
|
||||
$pc = match($riwayat->penyakit->tingkat_bahaya) {
|
||||
'Sangat Tinggi' => 'pill-danger-st',
|
||||
'Tinggi' => 'pill-danger-t',
|
||||
'Sedang' => 'pill-danger-s',
|
||||
default => 'pill-danger-r',
|
||||
'Sangat Tinggi' => 'pill-st',
|
||||
'Tinggi' => 'pill-t',
|
||||
'Sedang' => 'pill-s',
|
||||
default => 'pill-r',
|
||||
};
|
||||
@endphp
|
||||
<span class="pill {{ $pc }}">
|
||||
<svg width="10" height="10" fill="none" stroke="currentColor" viewBox="0 0 24 24" stroke-width="2.5"><path stroke-linecap="round" stroke-linejoin="round" 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"/></svg>
|
||||
<svg width="9" height="9" fill="none" stroke="currentColor" viewBox="0 0 24 24" stroke-width="2.5"><path stroke-linecap="round" stroke-linejoin="round" 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"/></svg>
|
||||
{{ $riwayat->penyakit->tingkat_bahaya }}
|
||||
</span>
|
||||
@endif
|
||||
</div>
|
||||
<div style="display:flex;align-items:flex-end;justify-content:space-between;gap:1rem;flex-wrap:wrap;">
|
||||
<div>
|
||||
<div class="disease-name">{{ $riwayat->penyakit->nama_penyakit ?? 'Tidak Teridentifikasi' }}</div>
|
||||
@if($riwayat->penyakit?->nama_latin)
|
||||
<div class="disease-latin">{{ $riwayat->penyakit->nama_latin }}</div>
|
||||
@endif
|
||||
</div>
|
||||
<a href="{{ route('user.riwayat.pdf', $riwayat->id_diagnosis) }}" target="_blank" class="btn-dl" style="flex-shrink:0;">
|
||||
<svg width="14" height="14" fill="none" stroke="currentColor" viewBox="0 0 24 24" stroke-width="2.2">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" d="M4 16v1a3 3 0 003 3h10a3 3 0 003-3v-1m-4-4l-4 4m0 0l-4-4m4 4V4"/>
|
||||
</svg>
|
||||
Download PDF
|
||||
<a href="{{ route('user.riwayat.pdf', $riwayat->id_diagnosis) }}" target="_blank" class="btn-dl">
|
||||
<svg width="13" height="13" fill="none" stroke="currentColor" viewBox="0 0 24 24" stroke-width="2.2"><path stroke-linecap="round" stroke-linejoin="round" d="M4 16v1a3 3 0 003 3h10a3 3 0 003-3v-1m-4-4l-4 4m0 0l-4-4m4 4V4"/></svg>
|
||||
Unduh Laporan PDF
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="date-meta">
|
||||
<div>{{ $riwayat->tanggal->format('d M Y') }}</div>
|
||||
<div>{{ $riwayat->tanggal->format('H:i') }} WIB</div>
|
||||
<small>ID: {{ $riwayat->id_diagnosis }}</small>
|
||||
<div class="date-big">{{ $riwayat->tanggal->format('d M Y') }}</div>
|
||||
<div class="date-time">{{ $riwayat->tanggal->format('H:i') }} WIB</div>
|
||||
<div class="date-id">{{ $riwayat->id_diagnosis }}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="cf-box">
|
||||
<div class="cf-row">
|
||||
<span class="cf-lbl">Tingkat Kepercayaan (Certainty Factor)</span>
|
||||
<span class="cf-val">{{ round($riwayat->cf_tertinggi * 100, 1) }}%</span>
|
||||
|
||||
<div class="cf-panel" style="margin-top:1.1rem;">
|
||||
<div class="cf-header">
|
||||
<span class="cf-label">Certainty Factor</span>
|
||||
<span class="cf-value">{{ round($riwayat->cf_tertinggi * 100, 1) }}<span style="font-size:1.2rem; opacity:.6;">%</span></span>
|
||||
</div>
|
||||
<div class="cf-track">
|
||||
<div class="cf-fill" style="width:{{ round($riwayat->cf_tertinggi * 100, 1) }}%;"></div>
|
||||
</div>
|
||||
<div class="cf-ticks"><span>0%</span><span>50%</span><span>100%</span></div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{-- Main two-column grid --}}
|
||||
{{-- LEFT = info & aksi (narrow) | RIGHT = konten detail (wide) --}}
|
||||
{{-- ── Main Grid ── --}}
|
||||
<div class="main-grid a2">
|
||||
|
||||
{{-- ── LEFT COLUMN ── --}}
|
||||
{{-- LEFT: image + actions --}}
|
||||
<div class="col-stack">
|
||||
|
||||
{{-- Aksi --}}
|
||||
@if($riwayat->penyakit?->gambar_url)
|
||||
<div class="card" style="overflow:hidden;">
|
||||
<img src="{{ $riwayat->penyakit->gambar_url }}"
|
||||
alt="{{ $riwayat->penyakit->nama_penyakit }}"
|
||||
class="img-card-img"
|
||||
onerror="this.style.display='none';">
|
||||
<div class="img-card-caption">{{ $riwayat->penyakit->nama_penyakit }}</div>
|
||||
</div>
|
||||
@endif
|
||||
|
||||
{{-- Actions --}}
|
||||
<div class="card">
|
||||
<div class="card-body" style="display:flex;flex-direction:column;gap:.65rem;">
|
||||
<a href="{{ route('user.diagnosa.index') }}" class="btn-main">
|
||||
<div class="card-body" style="display:flex; flex-direction:column; gap:.65rem;">
|
||||
<a href="{{ route('user.diagnosa.index') }}" class="btn-primary">
|
||||
<svg width="14" height="14" fill="none" stroke="currentColor" viewBox="0 0 24 24" stroke-width="2.2"><path stroke-linecap="round" stroke-linejoin="round" d="M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15"/></svg>
|
||||
Diagnosa Ulang
|
||||
</a>
|
||||
<a href="{{ route('user.diagnosa.riwayat') }}" class="btn-sec">
|
||||
<a href="{{ route('user.diagnosa.riwayat') }}" class="btn-secondary">
|
||||
<svg width="14" height="14" fill="none" stroke="currentColor" viewBox="0 0 24 24" stroke-width="2.2"><path stroke-linecap="round" stroke-linejoin="round" d="M10 19l-7-7m0 0l7-7m-7 7h18"/></svg>
|
||||
Kembali ke Riwayat
|
||||
</a>
|
||||
|
|
@ -285,10 +331,43 @@
|
|||
|
||||
</div>
|
||||
|
||||
{{-- ── RIGHT COLUMN (Solusi / Detail) ── --}}
|
||||
{{-- RIGHT: detail cards --}}
|
||||
<div class="col-stack a3">
|
||||
|
||||
{{-- Cara Pengendalian (Solusi) --}}
|
||||
{{-- Deskripsi penyakit --}}
|
||||
@if($riwayat->penyakit?->deskripsi_singkat)
|
||||
<div class="card">
|
||||
<div class="card-hdr">
|
||||
<div class="card-hdr-icon" style="background:#fef3c7;">
|
||||
<svg width="15" height="15" fill="none" stroke="#b45309" viewBox="0 0 24 24" stroke-width="2"><path stroke-linecap="round" stroke-linejoin="round" d="M12 6.253v13m0-13C10.832 5.477 9.246 5 7.5 5S4.168 5.477 3 6.253v13C4.168 18.477 5.754 18 7.5 18s3.332.477 4.5 1.253m0-13C13.168 5.477 14.754 5 16.5 5c1.747 0 3.332.477 4.5 1.253v13C19.832 18.477 18.247 18 16.5 18c-1.746 0-3.332.477-4.5 1.253"/></svg>
|
||||
</div>
|
||||
<span class="card-hdr-title">Tentang {{ ($riwayat->penyakit?->kategori === 'Hama') ? 'Hama' : 'Penyakit' }}</span>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="desc-box">{{ $riwayat->penyakit->deskripsi_singkat }}</div>
|
||||
|
||||
@if($riwayat->penyakit?->deskripsi_lengkap)
|
||||
<div style="margin-top:.75rem;">
|
||||
<button onclick="toggleDetail(this)"
|
||||
style="display:inline-flex;align-items:center;gap:.4rem;font-size:.75rem;font-weight:700;color:#b45309;background:#fef9c3;border:1.5px solid #fde68a;border-radius:8px;padding:.4rem .85rem;cursor:pointer;transition:all .2s;"
|
||||
onmouseover="this.style.background='#fef08a'" onmouseout="this.style.background='#fef9c3'">
|
||||
<svg class="detail-icon" width="13" height="13" fill="none" stroke="currentColor" viewBox="0 0 24 24" stroke-width="2.5" style="transition:transform .3s;">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" d="M19 9l-7 7-7-7"/>
|
||||
</svg>
|
||||
Lihat Detail
|
||||
</button>
|
||||
<div class="detail-content" style="display:none; margin-top:.65rem;">
|
||||
<div style="background:#fffbeb;border:1.5px solid #fde68a;border-radius:12px;padding:.9rem 1rem;font-size:.8rem;color:#78350f;line-height:1.7;">
|
||||
{{ $riwayat->penyakit->deskripsi_lengkap }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
@endif
|
||||
|
||||
{{-- Pengendalian --}}
|
||||
@if($riwayat->penyakit?->pengendalian_pencegahan || $riwayat->penyakit?->pengendalian_kimia || $riwayat->penyakit?->pengendalian_organik || $riwayat->penyakit?->pengendalian_budidaya)
|
||||
<div class="card">
|
||||
<div class="card-hdr">
|
||||
|
|
@ -350,28 +429,44 @@
|
|||
|
||||
{{-- Semua kemungkinan --}}
|
||||
@if($riwayat->hasil_diagnosa && count($riwayat->hasil_diagnosa) > 1)
|
||||
@php
|
||||
$kategoriList = collect($riwayat->hasil_diagnosa)
|
||||
->map(fn($h) => \App\Models\MasterPenyakit::find($h['id_penyakit'])?->kategori)
|
||||
->filter()
|
||||
->unique()
|
||||
->values();
|
||||
$labelKemung = $kategoriList->count() > 1
|
||||
? 'Semua Kemungkinan Hama & Penyakit'
|
||||
: 'Semua Kemungkinan ' . ($kategoriList->first() ?? 'Penyakit');
|
||||
@endphp
|
||||
<div class="card">
|
||||
<div class="card-hdr">
|
||||
<div class="card-hdr-icon" style="background:#ede9fe;">
|
||||
<svg width="15" height="15" fill="none" stroke="#7c3aed" viewBox="0 0 24 24" stroke-width="2"><path stroke-linecap="round" stroke-linejoin="round" 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"/></svg>
|
||||
</div>
|
||||
<span class="card-hdr-title">Semua Kemungkinan Penyakit</span>
|
||||
<span class="card-hdr-title">{{ $labelKemung }}</span>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="kemung-list">
|
||||
@foreach($riwayat->hasil_diagnosa as $i => $hasil)
|
||||
<div class="kemung-item {{ $i === 0 ? 'r1' : 'rother' }}">
|
||||
<span class="rank-circle {{ $i === 0 ? 'rc-1' : 'rc-other' }}">{{ $i+1 }}</span>
|
||||
<span style="flex:1;font-size:.8rem;font-weight:{{ $i===0?'700':'500' }};color:{{ $i===0?'#166534':'#374151' }};overflow:hidden;text-overflow:ellipsis;white-space:nowrap;">
|
||||
{{ $hasil['nama_penyakit'] }}
|
||||
</span>
|
||||
<div class="bar-track" style="max-width:90px;">
|
||||
<div class="bar-fill" style="width:{{ $hasil['persentase'] }}%;background:{{ $i===0?'#16a34a':'#d1d5db' }};"></div>
|
||||
@php $penyakitItem = \App\Models\MasterPenyakit::find($hasil['id_penyakit']); @endphp
|
||||
<div class="kemung-item {{ $i === 0 ? 'top' : 'rest' }}">
|
||||
<span class="rank-num {{ $i === 0 ? 'r1' : 'ro' }}">{{ $i + 1 }}</span>
|
||||
<div style="flex:1; min-width:0;">
|
||||
<span class="kemung-name {{ $i === 0 ? 'top' : '' }}">{{ $hasil['nama_penyakit'] }}</span>
|
||||
@if($penyakitItem?->nama_latin)
|
||||
<div style="font-size:.7rem; color:#9ca3af; font-style:italic; margin-top:.1rem;">{{ $penyakitItem->nama_latin }}</div>
|
||||
@endif
|
||||
</div>
|
||||
<span style="font-size:.8rem;font-weight:800;color:{{ $i===0?'#16a34a':'#9ca3af' }};width:36px;text-align:right;flex-shrink:0;">{{ $hasil['persentase'] }}%</span>
|
||||
<div class="bar-wrap">
|
||||
<div class="bar-fill-k" style="width:{{ $hasil['persentase'] }}%; background:{{ $i===0 ? '#16a34a' : '#d1d5db' }};"></div>
|
||||
</div>
|
||||
<span class="kemung-pct" style="color:{{ $i===0?'#16a34a':'#9ca3af' }};">{{ $hasil['persentase'] }}%</span>
|
||||
</div>
|
||||
@endforeach
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@endif
|
||||
|
||||
{{-- Relasi gejala --}}
|
||||
|
|
@ -383,29 +478,29 @@
|
|||
</div>
|
||||
<span class="card-hdr-title">Relasi Gejala & Penyakit</span>
|
||||
</div>
|
||||
<div class="relasi-wrap">
|
||||
<div class="relasi-outer">
|
||||
<table class="relasi-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th style="padding-left:1.2rem;">Gejala</th>
|
||||
<th style="padding-left:1.35rem;">Gejala</th>
|
||||
@foreach($riwayat->hasil_diagnosa as $hasil)
|
||||
<th>{{ $hasil['nama_penyakit'] }}<br><span style="color:#16a34a;text-transform:none;letter-spacing:0;font-weight:700;">{{ $hasil['persentase'] }}%</span></th>
|
||||
<th>{{ $hasil['nama_penyakit'] }}<br><span style="color:var(--leaf-mid);text-transform:none;letter-spacing:0;font-weight:700;">{{ $hasil['persentase'] }}%</span></th>
|
||||
@endforeach
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@foreach($gejalaInput as $gejala)
|
||||
<tr>
|
||||
<td style="padding-left:1.2rem;font-weight:500;">{{ $gejala->nama_gejala }}</td>
|
||||
<td style="padding-left:1.35rem;font-weight:500;">{{ $gejala->nama_gejala }}</td>
|
||||
@foreach($riwayat->hasil_diagnosa as $hasil)
|
||||
<td>
|
||||
@if(isset($relasiGejala[$hasil['id_penyakit']]) && $relasiGejala[$hasil['id_penyakit']]->contains('id_gejala', $gejala->id_gejala))
|
||||
<span class="chk-yes">
|
||||
<svg width="11" height="11" fill="none" stroke="#16a34a" viewBox="0 0 24 24" stroke-width="2.5"><path stroke-linecap="round" stroke-linejoin="round" d="M5 13l4 4L19 7"/></svg>
|
||||
<svg width="11" height="11" fill="none" stroke="var(--leaf)" viewBox="0 0 24 24" stroke-width="2.5"><path stroke-linecap="round" stroke-linejoin="round" d="M5 13l4 4L19 7"/></svg>
|
||||
</span>
|
||||
@else
|
||||
<span class="chk-no">
|
||||
<svg width="10" height="10" fill="none" stroke="#d1d5db" viewBox="0 0 24 24" stroke-width="2.5"><path stroke-linecap="round" stroke-linejoin="round" d="M6 18L18 6M6 6l12 12"/></svg>
|
||||
<svg width="10" height="10" fill="none" stroke="var(--fog)" viewBox="0 0 24 24" stroke-width="2.5"><path stroke-linecap="round" stroke-linejoin="round" d="M6 18L18 6M6 6l12 12"/></svg>
|
||||
</span>
|
||||
@endif
|
||||
</td>
|
||||
|
|
@ -414,9 +509,7 @@
|
|||
@endforeach
|
||||
</tbody>
|
||||
</table>
|
||||
<p style="font-size:.68rem;color:#9ca3af;padding:.65rem 1.2rem;border-top:1px solid #f3f4f6;">
|
||||
Centang = gejala terkait | Silang = tidak terkait
|
||||
</p>
|
||||
<p class="relasi-legend">✓ gejala terkait · ✗ tidak terkait</p>
|
||||
</div>
|
||||
</div>
|
||||
@endif
|
||||
|
|
@ -425,4 +518,22 @@
|
|||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<script>
|
||||
function toggleDetail(btn) {
|
||||
const content = btn.nextElementSibling;
|
||||
const icon = btn.querySelector('.detail-icon');
|
||||
const isOpen = content.style.display !== 'none';
|
||||
|
||||
if (isOpen) {
|
||||
content.style.display = 'none';
|
||||
icon.style.transform = 'rotate(0deg)';
|
||||
btn.innerHTML = btn.innerHTML.replace('Sembunyikan', 'Lihat Detail');
|
||||
} else {
|
||||
content.style.display = 'block';
|
||||
icon.style.transform = 'rotate(180deg)';
|
||||
btn.innerHTML = btn.innerHTML.replace('Lihat Detail', 'Sembunyikan');
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@endsection
|
||||
|
|
@ -7,112 +7,86 @@
|
|||
* { margin: 0; padding: 0; box-sizing: border-box; }
|
||||
body {
|
||||
font-family: 'DejaVu Sans', sans-serif;
|
||||
font-size: 11.5px;
|
||||
color: #1f2937;
|
||||
font-size: 11px;
|
||||
color: #0f1f14;
|
||||
background: #ffffff;
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
/* ── HEADER ── */
|
||||
.header { background: #1a4d2e; color: white; padding: 22px 28px 18px; }
|
||||
.header-top { width: 100%; border-collapse: collapse; margin-bottom: 12px; }
|
||||
.header-top td { vertical-align: top; }
|
||||
/* ── BANNER ── */
|
||||
.banner { background: #1a4d2e; color: white; padding: 22px 28px 20px; }
|
||||
|
||||
.badge {
|
||||
display: inline-block; padding: 2px 9px; border-radius: 999px;
|
||||
font-size: 8.5px; font-weight: bold; text-transform: uppercase;
|
||||
letter-spacing: 0.5px; background: rgba(255,255,255,0.15);
|
||||
border: 1px solid rgba(255,255,255,0.25); color: white;
|
||||
margin-right: 4px; margin-bottom: 4px;
|
||||
font-size: 8px; font-weight: bold; text-transform: uppercase;
|
||||
letter-spacing: 0.5px; background: rgba(255,255,255,0.13);
|
||||
border: 1px solid rgba(255,255,255,0.22); color: rgba(255,255,255,.9);
|
||||
margin-right: 4px; margin-bottom: 6px;
|
||||
}
|
||||
.badge-st { background: #dc2626; border-color: #dc2626; color: #fff; }
|
||||
.badge-t { background: #f97316; border-color: #f97316; color: #fff; }
|
||||
.badge-s { background: #fde047; border-color: #fde047; color: #713f12; }
|
||||
.badge-r { background: #bbf7d0; border-color: #bbf7d0; color: #14532d; }
|
||||
.badge-t { background: #ea580c; border-color: #ea580c; color: #fff; }
|
||||
.badge-s { background: #ca8a04; border-color: #ca8a04; color: #fff; }
|
||||
.badge-r { background: rgba(106,173,94,.25); border-color: rgba(106,173,94,.4); color: #a3e09a; }
|
||||
|
||||
.disease-name { font-size: 19px; font-weight: bold; color: #fff; margin: 8px 0 2px; }
|
||||
.disease-latin { font-style: italic; font-size: 10px; color: rgba(255,255,255,0.6); }
|
||||
.meta-date { text-align: right; font-size: 9.5px; color: rgba(255,255,255,0.55); }
|
||||
.meta-id { font-size: 8px; color: rgba(255,255,255,0.3); margin-top: 4px; }
|
||||
.disease-name { font-size: 20px; font-weight: bold; color: #fff; margin: 8px 0 3px; line-height: 1.2; }
|
||||
.disease-latin { font-style: italic; font-size: 10px; color: rgba(255,255,255,0.45); margin-bottom: 6px; }
|
||||
.meta-date { text-align: right; font-size: 9px; color: rgba(255,255,255,0.55); }
|
||||
.meta-time { font-size: 8.5px; color: rgba(255,255,255,.35); margin-top: 2px; }
|
||||
.meta-id { font-size: 7.5px; color: rgba(255,255,255,0.25); margin-top: 5px; }
|
||||
|
||||
.cf-box { background: rgba(0,0,0,0.22); border-radius: 9px; padding: 10px 14px; }
|
||||
.cf-inner { width: 100%; border-collapse: collapse; margin-bottom: 5px; }
|
||||
.cf-label { font-size: 10px; color: rgba(255,255,255,0.75); }
|
||||
.cf-value { font-size: 20px; font-weight: bold; color: #fff; text-align: right; }
|
||||
.cf-track { background: rgba(0,0,0,0.3); border-radius: 999px; height: 8px; width: 100%; }
|
||||
.cf-fill { background: #ffffff; border-radius: 999px; height: 8px; }
|
||||
.cf-ticks { width: 100%; border-collapse: collapse; margin-top: 2px; }
|
||||
.cf-ticks td { font-size: 8px; color: rgba(255,255,255,0.35); }
|
||||
.cf-box { background: rgba(0,0,0,0.22); border-radius: 9px; padding: 10px 14px; margin-top: 14px; }
|
||||
.cf-lbl { font-size: 8.5px; color: rgba(255,255,255,.55); text-transform: uppercase; letter-spacing: .05em; }
|
||||
.cf-val { font-size: 22px; font-weight: bold; color: #fff; text-align: right; line-height: 1; }
|
||||
.cf-track { background: rgba(0,0,0,0.3); border-radius: 999px; height: 7px; }
|
||||
.cf-fill { background: #ffffff; border-radius: 999px; height: 7px; }
|
||||
.cf-tick { font-size: 7.5px; color: rgba(255,255,255,.3); }
|
||||
|
||||
/* ── CONTENT ── */
|
||||
.content { padding: 18px 28px; }
|
||||
|
||||
/* two-col layout */
|
||||
.two-col { width: 100%; border-collapse: separate; border-spacing: 10px 0; }
|
||||
.two-col td { vertical-align: top; }
|
||||
.col-left { width: 38%; }
|
||||
.col-right { width: 62%; }
|
||||
|
||||
/* section wrapper */
|
||||
.section { margin-bottom: 14px; }
|
||||
|
||||
.section { margin-bottom: 16px; }
|
||||
.section-title {
|
||||
font-size: 10px; font-weight: bold; text-transform: uppercase;
|
||||
letter-spacing: 0.07em; color: #374151;
|
||||
padding-bottom: 5px; margin-bottom: 8px;
|
||||
font-size: 9.5px; font-weight: bold; text-transform: uppercase;
|
||||
letter-spacing: .07em; color: #374151;
|
||||
padding-bottom: 5px; margin-bottom: 9px;
|
||||
border-bottom: 2px solid #d1fae5;
|
||||
display: flex; align-items: center; gap: 5px;
|
||||
}
|
||||
.section-title-bar {
|
||||
display: inline-block; width: 3px; height: 12px;
|
||||
background: #2d7a4f; border-radius: 2px;
|
||||
margin-right: 4px; vertical-align: middle;
|
||||
margin-right: 5px; vertical-align: middle;
|
||||
}
|
||||
|
||||
/* info grid */
|
||||
.info-table { width: 100%; border-collapse: collapse; }
|
||||
.info-table tr td { padding: 5px 6px; font-size: 10.5px; border-bottom: 1px solid #f3f4f6; }
|
||||
.info-table tr:last-child td { border-bottom: none; }
|
||||
.info-table td:first-child { color: #6b7280; width: 42%; }
|
||||
.info-table td:last-child { font-weight: 600; color: #111827; }
|
||||
.val-green { color: #16a34a !important; }
|
||||
.val-blue { color: #2563eb !important; }
|
||||
|
||||
/* desc */
|
||||
.desc-box { background: #f9fafb; border-radius: 7px; padding: 10px; font-size: 10.5px; color: #4b5563; line-height: 1.6; }
|
||||
|
||||
/* gejala */
|
||||
.gejala-item {
|
||||
display: block; background: #f0fdf4; border: 1px solid #bbf7d0;
|
||||
border-radius: 5px; padding: 3px 8px 3px 6px;
|
||||
font-size: 10px; color: #166534; margin-bottom: 3px;
|
||||
/* Deskripsi */
|
||||
.desc-box {
|
||||
background: #f9fafb; border-radius: 7px; padding: 10px 12px;
|
||||
font-size: 10.5px; color: #4b5563; line-height: 1.65;
|
||||
}
|
||||
.gejala-check { color: #16a34a; font-weight: bold; margin-right: 3px; }
|
||||
|
||||
/* pengendalian */
|
||||
/* Pengendalian */
|
||||
.ctrl-table { width: 100%; border-collapse: separate; border-spacing: 5px; }
|
||||
.ctrl-table td { vertical-align: top; width: 50%; padding: 9px 10px; border-radius: 7px; font-size: 10px; line-height: 1.55; }
|
||||
.ctrl-label { font-weight: bold; font-size: 9.5px; margin-bottom: 4px; }
|
||||
.ctrl-label { font-weight: bold; font-size: 9px; margin-bottom: 4px; display: block; }
|
||||
.ctrl-pencegahan { background: #eff6ff; color: #1e40af; }
|
||||
.ctrl-kimia { background: #fff7ed; color: #c2410c; }
|
||||
.ctrl-organik { background: #f0fdf4; color: #15803d; }
|
||||
.ctrl-budidaya { background: #fefce8; color: #a16207; }
|
||||
|
||||
/* kemungkinan */
|
||||
/* Kemungkinan */
|
||||
.kemung-table { width: 100%; border-collapse: collapse; }
|
||||
.kemung-table thead tr { background: #f3f4f6; }
|
||||
.kemung-table th { padding: 6px 8px; text-align: left; font-size: 9px; font-weight: bold; color: #6b7280; text-transform: uppercase; }
|
||||
.kemung-table th { padding: 6px 8px; text-align: left; font-size: 8.5px; font-weight: bold; color: #6b7280; text-transform: uppercase; letter-spacing: .04em; }
|
||||
.kemung-table td { padding: 7px 8px; font-size: 10.5px; border-bottom: 1px solid #f3f4f6; vertical-align: middle; }
|
||||
.kemung-table tr:last-child td { border-bottom: none; }
|
||||
.rank-circle { display: inline-block; width: 20px; height: 20px; border-radius: 50%; text-align: center; line-height: 20px; font-size: 9px; font-weight: bold; color: white; }
|
||||
.rank-circle { display: inline-block; width: 20px; height: 20px; border-radius: 50%; text-align: center; line-height: 20px; font-size: 8.5px; font-weight: bold; color: white; }
|
||||
.rank-1 { background: #16a34a; }
|
||||
.rank-other { background: #9ca3af; }
|
||||
.mini-track { background: #e5e7eb; border-radius: 999px; height: 5px; width: 100%; }
|
||||
.mini-fill { border-radius: 999px; height: 5px; }
|
||||
|
||||
/* relasi */
|
||||
/* Relasi */
|
||||
.relasi-table { width: 100%; border-collapse: collapse; font-size: 9.5px; }
|
||||
.relasi-table th { background: #f9fafb; padding: 6px 7px; font-size: 8.5px; font-weight: bold; color: #6b7280; border: 1px solid #e5e7eb; text-align: center; }
|
||||
.relasi-table th { background: #f9fafb; padding: 6px 7px; font-size: 8px; font-weight: bold; color: #6b7280; border: 1px solid #e5e7eb; text-align: center; }
|
||||
.relasi-table th:first-child { text-align: left; }
|
||||
.relasi-table td { padding: 5px 7px; border: 1px solid #f3f4f6; text-align: center; }
|
||||
.relasi-table td:first-child { text-align: left; }
|
||||
|
|
@ -120,22 +94,21 @@
|
|||
.check-yes { color: #16a34a; font-weight: bold; font-size: 12px; }
|
||||
.check-no { color: #d1d5db; font-size: 12px; }
|
||||
|
||||
/* ── FOOTER ── */
|
||||
/* Footer */
|
||||
.footer { margin-top: 20px; background: #f0fdf4; border-top: 2px solid #d1fae5; }
|
||||
.footer-table { width: 100%; border-collapse: collapse; }
|
||||
.footer-table td { padding: 10px 28px; font-size: 8.5px; vertical-align: middle; }
|
||||
.footer-table td { padding: 10px 28px; font-size: 8px; vertical-align: middle; }
|
||||
.footer-note { color: #6b7280; font-style: italic; }
|
||||
.footer-id { color: #16a34a; font-weight: bold; text-align: right; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
{{-- ── HEADER ── --}}
|
||||
<div class="header">
|
||||
<table class="header-top">
|
||||
{{-- ── BANNER ── --}}
|
||||
<div class="banner">
|
||||
<table style="width:100%; border-collapse:collapse;">
|
||||
<tr>
|
||||
<td>
|
||||
{{-- Badges --}}
|
||||
<td style="vertical-align:top;">
|
||||
<span class="badge">Penyakit Terdeteksi</span>
|
||||
@if($riwayat->penyakit?->tingkat_bahaya)
|
||||
@php
|
||||
|
|
@ -148,38 +121,34 @@
|
|||
@endphp
|
||||
<span class="badge {{ $bc }}">{{ $riwayat->penyakit->tingkat_bahaya }}</span>
|
||||
@endif
|
||||
|
||||
<div class="disease-name">{{ $riwayat->penyakit->nama_penyakit ?? 'Tidak Teridentifikasi' }}</div>
|
||||
@if($riwayat->penyakit?->nama_latin)
|
||||
<div class="disease-latin">{{ $riwayat->penyakit->nama_latin }}</div>
|
||||
@endif
|
||||
</td>
|
||||
<td style="text-align:right; vertical-align:top;">
|
||||
<div class="meta-date">
|
||||
{{ $riwayat->tanggal->format('d M Y') }}<br>
|
||||
{{ $riwayat->tanggal->format('H:i') }} WIB
|
||||
</div>
|
||||
<div class="meta-id">ID: {{ $riwayat->id_diagnosis }}</div>
|
||||
<td style="text-align:right; vertical-align:top; white-space:nowrap;">
|
||||
<div class="meta-date">{{ $riwayat->tanggal->format('d M Y') }}</div>
|
||||
<div class="meta-time">{{ $riwayat->tanggal->format('H:i') }} WIB</div>
|
||||
<div class="meta-id">{{ $riwayat->id_diagnosis }}</div>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
{{-- CF bar --}}
|
||||
<div class="cf-box">
|
||||
<table class="cf-inner">
|
||||
<table style="width:100%; border-collapse:collapse; margin-bottom:6px;">
|
||||
<tr>
|
||||
<td class="cf-label">Tingkat Kepercayaan (Certainty Factor)</td>
|
||||
<td class="cf-value">{{ round($riwayat->cf_tertinggi * 100, 1) }}%</td>
|
||||
<td class="cf-lbl">Certainty Factor</td>
|
||||
<td class="cf-val">{{ round($riwayat->cf_tertinggi * 100, 1) }}<span style="font-size:13px; opacity:.6;">%</span></td>
|
||||
</tr>
|
||||
</table>
|
||||
<div class="cf-track">
|
||||
<div class="cf-fill" style="width:{{ round($riwayat->cf_tertinggi * 100, 1) }}%;"></div>
|
||||
</div>
|
||||
<table class="cf-ticks">
|
||||
<table style="width:100%; border-collapse:collapse; margin-top:3px;">
|
||||
<tr>
|
||||
<td>0%</td>
|
||||
<td style="text-align:center;">50%</td>
|
||||
<td style="text-align:right;">100%</td>
|
||||
<td class="cf-tick">0%</td>
|
||||
<td class="cf-tick" style="text-align:center;">50%</td>
|
||||
<td class="cf-tick" style="text-align:right;">100%</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
|
|
@ -188,7 +157,15 @@
|
|||
{{-- ── CONTENT ── --}}
|
||||
<div class="content">
|
||||
|
||||
{{-- Solusi / Pengendalian --}}
|
||||
{{-- Tentang Penyakit --}}
|
||||
@if($riwayat->penyakit?->deskripsi_singkat)
|
||||
<div class="section">
|
||||
<div class="section-title"><span class="section-title-bar"></span>Tentang Penyakit</div>
|
||||
<div class="desc-box">{{ $riwayat->penyakit->deskripsi_singkat }}</div>
|
||||
</div>
|
||||
@endif
|
||||
|
||||
{{-- Solusi & Pengendalian --}}
|
||||
@if($riwayat->penyakit?->pengendalian_pencegahan || $riwayat->penyakit?->pengendalian_kimia || $riwayat->penyakit?->pengendalian_organik || $riwayat->penyakit?->pengendalian_budidaya)
|
||||
<div class="section">
|
||||
<div class="section-title"><span class="section-title-bar"></span>Solusi & Cara Pengendalian</div>
|
||||
|
|
@ -196,7 +173,7 @@
|
|||
<tr>
|
||||
@if($riwayat->penyakit?->pengendalian_pencegahan)
|
||||
<td class="ctrl-pencegahan">
|
||||
<div class="ctrl-label">Pencegahan</div>
|
||||
<span class="ctrl-label">Pencegahan</span>
|
||||
{{ $riwayat->penyakit->pengendalian_pencegahan }}
|
||||
</td>
|
||||
@else
|
||||
|
|
@ -204,7 +181,7 @@
|
|||
@endif
|
||||
@if($riwayat->penyakit?->pengendalian_kimia)
|
||||
<td class="ctrl-kimia">
|
||||
<div class="ctrl-label">Pengendalian Kimia</div>
|
||||
<span class="ctrl-label">Pengendalian Kimia</span>
|
||||
{{ $riwayat->penyakit->pengendalian_kimia }}
|
||||
</td>
|
||||
@else
|
||||
|
|
@ -214,7 +191,7 @@
|
|||
<tr>
|
||||
@if($riwayat->penyakit?->pengendalian_organik)
|
||||
<td class="ctrl-organik">
|
||||
<div class="ctrl-label">Pengendalian Organik</div>
|
||||
<span class="ctrl-label">Pengendalian Organik</span>
|
||||
{{ $riwayat->penyakit->pengendalian_organik }}
|
||||
</td>
|
||||
@else
|
||||
|
|
@ -222,7 +199,7 @@
|
|||
@endif
|
||||
@if($riwayat->penyakit?->pengendalian_budidaya)
|
||||
<td class="ctrl-budidaya">
|
||||
<div class="ctrl-label">Pengendalian Budidaya</div>
|
||||
<span class="ctrl-label">Pengendalian Budidaya</span>
|
||||
{{ $riwayat->penyakit->pengendalian_budidaya }}
|
||||
</td>
|
||||
@else
|
||||
|
|
@ -242,7 +219,7 @@
|
|||
<tr>
|
||||
<th style="width:32px;">#</th>
|
||||
<th>Nama Penyakit</th>
|
||||
<th style="width:52px; text-align:right;">Akurasi</th>
|
||||
<th style="width:55px; text-align:right;">Akurasi</th>
|
||||
<th style="width:110px;">Grafik</th>
|
||||
</tr>
|
||||
</thead>
|
||||
|
|
@ -298,7 +275,7 @@
|
|||
@endforeach
|
||||
</tbody>
|
||||
</table>
|
||||
<p style="font-size:8px; color:#9ca3af; margin-top:5px;">✓ = gejala terkait penyakit | ✗ = tidak terkait</p>
|
||||
<p style="font-size:8px; color:#9ca3af; margin-top:5px;">✓ = gejala terkait | ✗ = tidak terkait</p>
|
||||
</div>
|
||||
@endif
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,10 @@
|
|||
<?php
|
||||
$targetPath = __DIR__ . '/storage/app/public';
|
||||
$linkPath = __DIR__ . '/public/storage';
|
||||
|
||||
if (!file_exists($linkPath)) {
|
||||
symlink($targetPath, $linkPath);
|
||||
echo "Storage link created!";
|
||||
} else {
|
||||
echo "Storage link already exists!";
|
||||
}
|
||||
Loading…
Reference in New Issue