Fix tambah admin
This commit is contained in:
parent
c05f121ecd
commit
e08b7f011b
|
|
@ -0,0 +1,138 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Controllers;
|
||||||
|
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
use App\Models\User;
|
||||||
|
use Illuminate\Support\Facades\Hash;
|
||||||
|
use Illuminate\Support\Facades\Validator;
|
||||||
|
|
||||||
|
class AdminController extends Controller
|
||||||
|
{
|
||||||
|
public function index()
|
||||||
|
{
|
||||||
|
if (!session('admin_logged_in')) {
|
||||||
|
return redirect()->route('admin.login')->with('error', 'Silakan login terlebih dahulu.');
|
||||||
|
}
|
||||||
|
|
||||||
|
$admins = User::where('role', 'admin')->get();
|
||||||
|
\Log::info('Admins fetched for UI', ['count' => $admins->count(), 'admins' => $admins->pluck('email')->toArray()]);
|
||||||
|
|
||||||
|
return view('Admin.manage-admin', compact('admins'));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function store(Request $request)
|
||||||
|
{
|
||||||
|
if (!session('admin_logged_in')) {
|
||||||
|
return response()->json(['error' => 'Unauthorized'], 401);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Debug log
|
||||||
|
\Log::info('Admin store request data', ['request_data' => $request->all()]);
|
||||||
|
|
||||||
|
$validator = Validator::make($request->all(), [
|
||||||
|
'name' => 'required|string|max:255',
|
||||||
|
'email' => 'required|string|email|max:255|unique:users',
|
||||||
|
'password' => 'required|string|min:6',
|
||||||
|
'role' => 'required|in:admin'
|
||||||
|
]);
|
||||||
|
|
||||||
|
if ($validator->fails()) {
|
||||||
|
return response()->json(['errors' => $validator->errors()], 422);
|
||||||
|
}
|
||||||
|
|
||||||
|
$admin = User::create([
|
||||||
|
'name' => $request->name,
|
||||||
|
'email' => $request->email,
|
||||||
|
'password' => Hash::make($request->password),
|
||||||
|
'role' => $request->role,
|
||||||
|
'email_verified_at' => now()
|
||||||
|
]);
|
||||||
|
|
||||||
|
return response()->json(['success' => 'Admin berhasil ditambahkan', 'admin' => $admin]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function edit($id)
|
||||||
|
{
|
||||||
|
if (!session('admin_logged_in')) {
|
||||||
|
return response()->json(['error' => 'Unauthorized'], 401);
|
||||||
|
}
|
||||||
|
|
||||||
|
$admin = User::findOrFail($id);
|
||||||
|
return response()->json($admin);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function update(Request $request, $id)
|
||||||
|
{
|
||||||
|
if (!session('admin_logged_in')) {
|
||||||
|
return response()->json(['error' => 'Unauthorized'], 401);
|
||||||
|
}
|
||||||
|
|
||||||
|
$admin = User::findOrFail($id);
|
||||||
|
|
||||||
|
$validator = Validator::make($request->all(), [
|
||||||
|
'name' => 'required|string|max:255',
|
||||||
|
'email' => 'required|string|email|max:255|unique:users,email,'.$id,
|
||||||
|
'role' => 'required|in:admin'
|
||||||
|
]);
|
||||||
|
|
||||||
|
if ($validator->fails()) {
|
||||||
|
return response()->json(['errors' => $validator->errors()], 422);
|
||||||
|
}
|
||||||
|
|
||||||
|
$admin->update([
|
||||||
|
'name' => $request->name,
|
||||||
|
'email' => $request->email,
|
||||||
|
'role' => $request->role
|
||||||
|
]);
|
||||||
|
|
||||||
|
if ($request->filled('password')) {
|
||||||
|
$admin->update(['password' => Hash::make($request->password)]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return response()->json(['success' => 'Admin berhasil diperbarui', 'admin' => $admin]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function destroy($id)
|
||||||
|
{
|
||||||
|
if (!session('admin_logged_in')) {
|
||||||
|
return response()->json(['error' => 'Unauthorized'], 401);
|
||||||
|
}
|
||||||
|
|
||||||
|
$admin = User::findOrFail($id);
|
||||||
|
|
||||||
|
// Prevent deleting the currently logged in admin
|
||||||
|
if ($admin->id == session('admin_user_id')) {
|
||||||
|
return response()->json(['error' => 'Tidak dapat menghapus akun yang sedang digunakan'], 422);
|
||||||
|
}
|
||||||
|
|
||||||
|
$admin->delete();
|
||||||
|
|
||||||
|
return response()->json(['success' => 'Admin berhasil dihapus']);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function toggleStatus($id)
|
||||||
|
{
|
||||||
|
if (!session('admin_logged_in')) {
|
||||||
|
return response()->json(['error' => 'Unauthorized'], 401);
|
||||||
|
}
|
||||||
|
|
||||||
|
$admin = User::findOrFail($id);
|
||||||
|
|
||||||
|
// Prevent deactivating the currently logged in admin
|
||||||
|
if ($admin->id == session('admin_user_id')) {
|
||||||
|
return response()->json(['error' => 'Tidak dapat menonaktifkan akun yang sedang digunakan'], 422);
|
||||||
|
}
|
||||||
|
|
||||||
|
// For simplicity, we'll use email_verified_at as status indicator
|
||||||
|
if ($admin->email_verified_at) {
|
||||||
|
$admin->update(['email_verified_at' => null]);
|
||||||
|
$status = 'inactive';
|
||||||
|
} else {
|
||||||
|
$admin->update(['email_verified_at' => now()]);
|
||||||
|
$status = 'active';
|
||||||
|
}
|
||||||
|
|
||||||
|
return response()->json(['success' => "Status admin berhasil diubah menjadi $status", 'status' => $status]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -13,11 +13,16 @@ class AdminSeeder extends Seeder
|
||||||
*/
|
*/
|
||||||
public function run(): void
|
public function run(): void
|
||||||
{
|
{
|
||||||
|
// Clear existing admin users first
|
||||||
|
DB::table('users')->where('role', 'admin')->delete();
|
||||||
|
|
||||||
|
// Create single admin user
|
||||||
DB::table('users')->insert([
|
DB::table('users')->insert([
|
||||||
'name' => 'Admin',
|
'name' => 'Admin',
|
||||||
'email' => 'admin@gmail.com',
|
'email' => 'admin@gmail.com',
|
||||||
'password' => Hash::make('admin123'),
|
'password' => Hash::make('admin123'),
|
||||||
'role' => 'admin',
|
'role' => 'admin',
|
||||||
|
'email_verified_at' => now(),
|
||||||
'created_at' => now(),
|
'created_at' => now(),
|
||||||
'updated_at' => now(),
|
'updated_at' => now(),
|
||||||
]);
|
]);
|
||||||
|
|
|
||||||
|
|
@ -47,12 +47,12 @@
|
||||||
<div class="w-12 h-12 bg-orange-100 rounded-xl flex items-center justify-center">
|
<div class="w-12 h-12 bg-orange-100 rounded-xl flex items-center justify-center">
|
||||||
<i class="fas fa-users text-orange-600 text-xl"></i>
|
<i class="fas fa-users text-orange-600 text-xl"></i>
|
||||||
</div>
|
</div>
|
||||||
<span class="text-xs text-gray-600 font-medium bg-gray-50 px-2 py-1 rounded-full">
|
<span class="text-xs bg-orange-100 text-orange-800 font-medium px-3 py-1 rounded-full">
|
||||||
0%
|
{{ App\Models\User::where('role', 'admin')->count() }}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<h3 class="text-2xl font-bold text-gray-900 mb-1">5</h3>
|
<h3 class="text-lg font-bold text-gray-900 mb-1">Admin Aktif</h3>
|
||||||
<p class="text-sm text-gray-600">Admin Aktif</p>
|
<p class="text-sm text-gray-600">Total admin terdaftar</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Data Hari Ini Card -->
|
<!-- Data Hari Ini Card -->
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,9 @@
|
||||||
<!-- Font Awesome for Icons -->
|
<!-- Font Awesome for Icons -->
|
||||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
|
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
|
||||||
|
|
||||||
|
<!-- CSRF Token -->
|
||||||
|
<meta name="csrf-token" content="{{ csrf_token() }}">
|
||||||
|
|
||||||
<!-- Chart.js (only load on pages that need it) -->
|
<!-- Chart.js (only load on pages that need it) -->
|
||||||
@if(request()->routeIs('admin.dashboard') || request()->routeIs('admin.system-statistics'))
|
@if(request()->routeIs('admin.dashboard') || request()->routeIs('admin.system-statistics'))
|
||||||
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
|
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
|
||||||
|
|
@ -26,6 +29,155 @@
|
||||||
font-family: 'Inter', sans-serif;
|
font-family: 'Inter', sans-serif;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Dark Mode Styles */
|
||||||
|
.dark {
|
||||||
|
background-color: #1a1a1a;
|
||||||
|
color: #e5e5e5;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dark .bg-white {
|
||||||
|
background-color: #2d2d2d !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dark .bg-gray-50 {
|
||||||
|
background-color: #1f1f1f !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dark .bg-gray-100 {
|
||||||
|
background-color: #2d2d2d !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dark .text-gray-900 {
|
||||||
|
color: #e5e5e5 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dark .text-gray-800 {
|
||||||
|
color: #d4d4d4 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dark .text-gray-700 {
|
||||||
|
color: #b3b3b3 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dark .text-gray-600 {
|
||||||
|
color: #999999 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dark .text-gray-500 {
|
||||||
|
color: #808080 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dark .border-gray-200 {
|
||||||
|
border-color: #404040 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dark .border-gray-300 {
|
||||||
|
border-color: #404040 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dark .hover\:bg-gray-50:hover {
|
||||||
|
background-color: #2d2d2d !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dark .hover\:bg-gray-100:hover {
|
||||||
|
background-color: #3d3d3d !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dark .hover\:bg-blue-50:hover {
|
||||||
|
background-color: #1e3a5f !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dark .hover\:bg-orange-50:hover {
|
||||||
|
background-color: #5c3d1e !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dark .hover\:bg-red-50:hover {
|
||||||
|
background-color: #5c1e1e !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dark .divide-gray-200 > :not([hidden]) ~ :not([hidden]) {
|
||||||
|
border-color: #404040 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dark .shadow-sm {
|
||||||
|
box-shadow: 0 1px 2px 0 rgba(255, 255, 255, 0.05) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dark .bg-gradient-to-r {
|
||||||
|
background-image: none !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dark .btn-primary {
|
||||||
|
background-color: #dc2626 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dark .btn-primary:hover {
|
||||||
|
background-color: #b91c1c !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Modal Dark Mode */
|
||||||
|
.dark .fixed.inset-0 {
|
||||||
|
background-color: rgba(0, 0, 0, 0.8) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dark .fixed.inset-0 > .bg-white {
|
||||||
|
background-color: #2d2d2d !important;
|
||||||
|
color: #e5e5e5 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dark .text-gray-700 {
|
||||||
|
color: #b3b3b3 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Form elements dark mode */
|
||||||
|
.dark input, .dark select, .dark textarea {
|
||||||
|
background-color: #3d3d3d !important;
|
||||||
|
border-color: #404040 !important;
|
||||||
|
color: #e5e5e5 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dark input:focus, .dark select:focus, .dark textarea:focus {
|
||||||
|
border-color: #dc2626 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Sidebar dark mode */
|
||||||
|
.dark .bg-gradient-to-b {
|
||||||
|
background-image: none !important;
|
||||||
|
background-color: #1f1f1f !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dark .sidebar-link {
|
||||||
|
color: #b3b3b3 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dark .sidebar-link:hover {
|
||||||
|
color: #e5e5e5 !important;
|
||||||
|
background-color: #2d2d2d !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dark .sidebar-link.active {
|
||||||
|
color: #ffffff !important;
|
||||||
|
background-color: #dc2626 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sidebar-link.active {
|
||||||
|
background-color: #dc2626 !important;
|
||||||
|
color: white !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sidebar-link:hover {
|
||||||
|
background-color: #f3f4f6 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Admin card dark mode */
|
||||||
|
.dark .hover\:bg-gray-50:hover {
|
||||||
|
background-color: #2d2d2d !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dark .border-t.border-gray-100 {
|
||||||
|
border-color: #404040 !important;
|
||||||
|
}
|
||||||
|
|
||||||
.stat-card {
|
.stat-card {
|
||||||
transition: all 0.3s ease;
|
transition: all 0.3s ease;
|
||||||
}
|
}
|
||||||
|
|
@ -117,6 +269,11 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="flex items-center space-x-4">
|
<div class="flex items-center space-x-4">
|
||||||
|
<!-- Dark Mode Toggle -->
|
||||||
|
<button id="darkModeToggle" class="relative p-2 text-gray-600 hover:text-gray-900 transition-colors" title="Toggle Dark Mode">
|
||||||
|
<i class="fas fa-moon text-xl" id="darkModeIcon"></i>
|
||||||
|
</button>
|
||||||
|
|
||||||
<button class="relative p-2 text-gray-600 hover:text-gray-900 transition-colors">
|
<button class="relative p-2 text-gray-600 hover:text-gray-900 transition-colors">
|
||||||
<i class="fas fa-bell text-xl"></i>
|
<i class="fas fa-bell text-xl"></i>
|
||||||
<span class="absolute top-1 right-1 w-2 h-2 bg-red-500 rounded-full"></span>
|
<span class="absolute top-1 right-1 w-2 h-2 bg-red-500 rounded-full"></span>
|
||||||
|
|
@ -144,8 +301,42 @@
|
||||||
|
|
||||||
<!-- Common JavaScript -->
|
<!-- Common JavaScript -->
|
||||||
<script>
|
<script>
|
||||||
// Common functionality for all pages
|
// Dark Mode Toggle
|
||||||
document.addEventListener('DOMContentLoaded', function() {
|
document.addEventListener('DOMContentLoaded', function() {
|
||||||
|
const darkModeToggle = document.getElementById('darkModeToggle');
|
||||||
|
const darkModeIcon = document.getElementById('darkModeIcon');
|
||||||
|
const html = document.documentElement;
|
||||||
|
|
||||||
|
// Check for saved theme preference or default to light mode
|
||||||
|
const currentTheme = localStorage.getItem('theme') || 'light';
|
||||||
|
if (currentTheme === 'dark') {
|
||||||
|
html.classList.add('dark');
|
||||||
|
darkModeIcon.classList.remove('fa-moon');
|
||||||
|
darkModeIcon.classList.add('fa-sun');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Toggle dark mode
|
||||||
|
darkModeToggle.addEventListener('click', function() {
|
||||||
|
const isDark = html.classList.contains('dark');
|
||||||
|
|
||||||
|
if (isDark) {
|
||||||
|
html.classList.remove('dark');
|
||||||
|
darkModeIcon.classList.remove('fa-sun');
|
||||||
|
darkModeIcon.classList.add('fa-moon');
|
||||||
|
localStorage.setItem('theme', 'light');
|
||||||
|
} else {
|
||||||
|
html.classList.add('dark');
|
||||||
|
darkModeIcon.classList.remove('fa-moon');
|
||||||
|
darkModeIcon.classList.add('fa-sun');
|
||||||
|
localStorage.setItem('theme', 'dark');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update chart colors if charts exist
|
||||||
|
if (window.updateChartTheme) {
|
||||||
|
updateChartTheme(!isDark);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
// Initialize tooltips and other common UI elements
|
// Initialize tooltips and other common UI elements
|
||||||
console.log('Admin Dashboard loaded');
|
console.log('Admin Dashboard loaded');
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -25,9 +25,6 @@
|
||||||
<table class="w-full">
|
<table class="w-full">
|
||||||
<thead class="bg-gray-50 border-b border-gray-200">
|
<thead class="bg-gray-50 border-b border-gray-200">
|
||||||
<tr>
|
<tr>
|
||||||
<th class="px-6 py-4 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">
|
|
||||||
Foto
|
|
||||||
</th>
|
|
||||||
<th class="px-6 py-4 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">
|
<th class="px-6 py-4 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">
|
||||||
Nama
|
Nama
|
||||||
</th>
|
</th>
|
||||||
|
|
@ -43,150 +40,53 @@
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody class="bg-white divide-y divide-gray-200">
|
<tbody class="bg-white divide-y divide-gray-200">
|
||||||
<!-- Admin Row 1 -->
|
@forelse ($admins as $admin)
|
||||||
<tr class="table-row">
|
<tr class="table-row" data-id="{{ $admin->id }}">
|
||||||
<td class="px-6 py-4 whitespace-nowrap">
|
<td class="px-6 py-4 whitespace-nowrap">
|
||||||
<img src="https://picsum.photos/seed/admin1/50/50.jpg"
|
<div class="text-sm font-medium text-gray-900">{{ $admin->name }}</div>
|
||||||
alt="Admin"
|
<div class="text-xs {{ $admin->email_verified_at ? 'text-green-500' : 'text-gray-500' }}">
|
||||||
class="w-12 h-12 rounded-full object-cover border-2 border-gray-200">
|
{{ $admin->email_verified_at ? 'Active' : 'Inactive' }}
|
||||||
</td>
|
</div>
|
||||||
<td class="px-6 py-4 whitespace-nowrap">
|
|
||||||
<div class="text-sm font-medium text-gray-900">Ahmad Wijaya</div>
|
|
||||||
<div class="text-xs text-gray-500">Active</div>
|
|
||||||
</td>
|
</td>
|
||||||
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-900">
|
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-900">
|
||||||
ahmad.wijaya@example.com
|
{{ $admin->email }}
|
||||||
</td>
|
</td>
|
||||||
<td class="px-6 py-4 whitespace-nowrap">
|
<td class="px-6 py-4 whitespace-nowrap">
|
||||||
<span class="px-3 py-1 inline-flex text-xs leading-5 font-semibold rounded-full bg-purple-100 text-purple-800">
|
@php
|
||||||
Super Admin
|
$roleClass = [
|
||||||
|
'admin' => 'bg-blue-100 text-blue-800'
|
||||||
|
];
|
||||||
|
$roleLabel = [
|
||||||
|
'admin' => 'Admin'
|
||||||
|
];
|
||||||
|
@endphp
|
||||||
|
<span class="px-3 py-1 inline-flex text-xs leading-5 font-semibold rounded-full {{ $roleClass[$admin->role] ?? 'bg-gray-100 text-gray-800' }}">
|
||||||
|
{{ $roleLabel[$admin->role] ?? ucfirst($admin->role) }}
|
||||||
</span>
|
</span>
|
||||||
</td>
|
</td>
|
||||||
<td class="px-6 py-4 whitespace-nowrap text-sm font-medium">
|
<td class="px-6 py-4 whitespace-nowrap text-sm font-medium">
|
||||||
<button class="btn-action text-blue-600 hover:text-blue-900 mr-3 transition-colors">
|
<button class="btn-action text-blue-600 hover:text-blue-900 mr-3 transition-colors cursor-pointer hover:bg-blue-50 p-2 rounded"
|
||||||
|
onclick="editAdmin({{ $admin->id }})"
|
||||||
|
title="Edit Admin">
|
||||||
<i class="fas fa-edit"></i>
|
<i class="fas fa-edit"></i>
|
||||||
</button>
|
</button>
|
||||||
<button class="btn-action text-red-600 hover:text-red-900 transition-colors">
|
<button class="btn-action text-red-600 hover:text-red-900 transition-colors cursor-pointer hover:bg-red-50 p-2 rounded"
|
||||||
|
onclick="deleteAdmin({{ $admin->id }})"
|
||||||
|
title="Hapus Admin">
|
||||||
<i class="fas fa-trash"></i>
|
<i class="fas fa-trash"></i>
|
||||||
</button>
|
</button>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
@empty
|
||||||
<!-- Admin Row 2 -->
|
<tr>
|
||||||
<tr class="table-row">
|
<td colspan="4" class="px-6 py-8 text-center text-gray-500">
|
||||||
<td class="px-6 py-4 whitespace-nowrap">
|
<div class="flex flex-col items-center">
|
||||||
<img src="https://picsum.photos/seed/admin2/50/50.jpg"
|
<i class="fas fa-users text-4xl mb-2 text-gray-300"></i>
|
||||||
alt="Admin"
|
<span>Belum ada data admin</span>
|
||||||
class="w-12 h-12 rounded-full object-cover border-2 border-gray-200">
|
</div>
|
||||||
</td>
|
|
||||||
<td class="px-6 py-4 whitespace-nowrap">
|
|
||||||
<div class="text-sm font-medium text-gray-900">Siti Nurhaliza</div>
|
|
||||||
<div class="text-xs text-gray-500">Active</div>
|
|
||||||
</td>
|
|
||||||
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-900">
|
|
||||||
siti.nurhaliza@example.com
|
|
||||||
</td>
|
|
||||||
<td class="px-6 py-4 whitespace-nowrap">
|
|
||||||
<span class="px-3 py-1 inline-flex text-xs leading-5 font-semibold rounded-full bg-blue-100 text-blue-800">
|
|
||||||
Admin
|
|
||||||
</span>
|
|
||||||
</td>
|
|
||||||
<td class="px-6 py-4 whitespace-nowrap text-sm font-medium">
|
|
||||||
<button class="btn-action text-blue-600 hover:text-blue-900 mr-3 transition-colors">
|
|
||||||
<i class="fas fa-edit"></i>
|
|
||||||
</button>
|
|
||||||
<button class="btn-action text-red-600 hover:text-red-900 transition-colors">
|
|
||||||
<i class="fas fa-trash"></i>
|
|
||||||
</button>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
|
|
||||||
<!-- Admin Row 3 -->
|
|
||||||
<tr class="table-row">
|
|
||||||
<td class="px-6 py-4 whitespace-nowrap">
|
|
||||||
<img src="https://picsum.photos/seed/admin3/50/50.jpg"
|
|
||||||
alt="Admin"
|
|
||||||
class="w-12 h-12 rounded-full object-cover border-2 border-gray-200">
|
|
||||||
</td>
|
|
||||||
<td class="px-6 py-4 whitespace-nowrap">
|
|
||||||
<div class="text-sm font-medium text-gray-900">Budi Santoso</div>
|
|
||||||
<div class="text-xs text-gray-500">Active</div>
|
|
||||||
</td>
|
|
||||||
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-900">
|
|
||||||
budi.santoso@example.com
|
|
||||||
</td>
|
|
||||||
<td class="px-6 py-4 whitespace-nowrap">
|
|
||||||
<span class="px-3 py-1 inline-flex text-xs leading-5 font-semibold rounded-full bg-blue-100 text-blue-800">
|
|
||||||
Admin
|
|
||||||
</span>
|
|
||||||
</td>
|
|
||||||
<td class="px-6 py-4 whitespace-nowrap text-sm font-medium">
|
|
||||||
<button class="btn-action text-blue-600 hover:text-blue-900 mr-3 transition-colors">
|
|
||||||
<i class="fas fa-edit"></i>
|
|
||||||
</button>
|
|
||||||
<button class="btn-action text-red-600 hover:text-red-900 transition-colors">
|
|
||||||
<i class="fas fa-trash"></i>
|
|
||||||
</button>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
|
|
||||||
<!-- Admin Row 4 -->
|
|
||||||
<tr class="table-row">
|
|
||||||
<td class="px-6 py-4 whitespace-nowrap">
|
|
||||||
<img src="https://picsum.photos/seed/admin4/50/50.jpg"
|
|
||||||
alt="Admin"
|
|
||||||
class="w-12 h-12 rounded-full object-cover border-2 border-gray-200">
|
|
||||||
</td>
|
|
||||||
<td class="px-6 py-4 whitespace-nowrap">
|
|
||||||
<div class="text-sm font-medium text-gray-900">Dewi Lestari</div>
|
|
||||||
<div class="text-xs text-gray-500">Inactive</div>
|
|
||||||
</td>
|
|
||||||
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-900">
|
|
||||||
dewi.lestari@example.com
|
|
||||||
</td>
|
|
||||||
<td class="px-6 py-4 whitespace-nowrap">
|
|
||||||
<span class="px-3 py-1 inline-flex text-xs leading-5 font-semibold rounded-full bg-blue-100 text-blue-800">
|
|
||||||
Admin
|
|
||||||
</span>
|
|
||||||
</td>
|
|
||||||
<td class="px-6 py-4 whitespace-nowrap text-sm font-medium">
|
|
||||||
<button class="btn-action text-blue-600 hover:text-blue-900 mr-3 transition-colors">
|
|
||||||
<i class="fas fa-edit"></i>
|
|
||||||
</button>
|
|
||||||
<button class="btn-action text-red-600 hover:text-red-900 transition-colors">
|
|
||||||
<i class="fas fa-trash"></i>
|
|
||||||
</button>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
|
|
||||||
<!-- Admin Row 5 -->
|
|
||||||
<tr class="table-row">
|
|
||||||
<td class="px-6 py-4 whitespace-nowrap">
|
|
||||||
<img src="https://picsum.photos/seed/admin5/50/50.jpg"
|
|
||||||
alt="Admin"
|
|
||||||
class="w-12 h-12 rounded-full object-cover border-2 border-gray-200">
|
|
||||||
</td>
|
|
||||||
<td class="px-6 py-4 whitespace-nowrap">
|
|
||||||
<div class="text-sm font-medium text-gray-900">Rizki Pratama</div>
|
|
||||||
<div class="text-xs text-gray-500">Active</div>
|
|
||||||
</td>
|
|
||||||
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-900">
|
|
||||||
rizki.pratama@example.com
|
|
||||||
</td>
|
|
||||||
<td class="px-6 py-4 whitespace-nowrap">
|
|
||||||
<span class="px-3 py-1 inline-flex text-xs leading-5 font-semibold rounded-full bg-green-100 text-green-800">
|
|
||||||
Moderator
|
|
||||||
</span>
|
|
||||||
</td>
|
|
||||||
<td class="px-6 py-4 whitespace-nowrap text-sm font-medium">
|
|
||||||
<button class="btn-action text-blue-600 hover:text-blue-900 mr-3 transition-colors">
|
|
||||||
<i class="fas fa-edit"></i>
|
|
||||||
</button>
|
|
||||||
<button class="btn-action text-red-600 hover:text-red-900 transition-colors">
|
|
||||||
<i class="fas fa-trash"></i>
|
|
||||||
</button>
|
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
@endforelse
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -194,33 +94,237 @@ class="w-12 h-12 rounded-full object-cover border-2 border-gray-200">
|
||||||
@endsection
|
@endsection
|
||||||
|
|
||||||
@section('scripts')
|
@section('scripts')
|
||||||
|
<style>
|
||||||
|
.btn-action {
|
||||||
|
transition: all 0.2s ease;
|
||||||
|
transform: scale(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-action:hover {
|
||||||
|
transform: scale(1.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-action:active {
|
||||||
|
transform: scale(0.95);
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<!-- Add Admin Modal -->
|
||||||
|
<div id="adminModal" class="fixed inset-0 bg-black bg-opacity-50 hidden z-50 flex items-center justify-center">
|
||||||
|
<div class="bg-white rounded-xl p-6 w-full max-w-md mx-4">
|
||||||
|
<div class="flex justify-between items-center mb-4">
|
||||||
|
<h3 id="modalTitle" class="text-xl font-semibold text-gray-900">Tambah Admin</h3>
|
||||||
|
<button onclick="closeModal()" class="text-gray-400 hover:text-gray-600">
|
||||||
|
<i class="fas fa-times"></i>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<form id="adminForm" onsubmit="saveAdmin(event)">
|
||||||
|
@csrf
|
||||||
|
<input type="hidden" id="adminId" name="id">
|
||||||
|
|
||||||
|
<div class="mb-4">
|
||||||
|
<label class="block text-sm font-medium text-gray-700 mb-2">Nama</label>
|
||||||
|
<input type="text" id="name" name="name" required
|
||||||
|
class="w-full px-3 py-2 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-red-500">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="mb-4">
|
||||||
|
<label class="block text-sm font-medium text-gray-700 mb-2">Email</label>
|
||||||
|
<input type="email" id="email" name="email" required
|
||||||
|
class="w-full px-3 py-2 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-red-500">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="mb-4">
|
||||||
|
<label class="block text-sm font-medium text-gray-700 mb-2">Password</label>
|
||||||
|
<input type="password" id="password" name="password"
|
||||||
|
class="w-full px-3 py-2 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-red-500">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="mb-6">
|
||||||
|
<label class="block text-sm font-medium text-gray-700 mb-2">Role</label>
|
||||||
|
<select id="role" name="role" required
|
||||||
|
class="w-full px-3 py-2 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-red-500">
|
||||||
|
<option value="admin">Admin</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="flex justify-end space-x-3">
|
||||||
|
<button type="button" onclick="closeModal()"
|
||||||
|
class="px-4 py-2 text-gray-700 bg-gray-200 rounded-lg hover:bg-gray-300 transition-colors">
|
||||||
|
Batal
|
||||||
|
</button>
|
||||||
|
<button type="submit" onclick="console.log('Submit button clicked');"
|
||||||
|
class="px-4 py-2 bg-red-500 text-white rounded-lg hover:bg-red-600 transition-colors">
|
||||||
|
Simpan
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
let currentEditId = null;
|
||||||
|
|
||||||
// Add Admin Modal functionality
|
// Add Admin Modal functionality
|
||||||
document.addEventListener('DOMContentLoaded', function() {
|
document.addEventListener('DOMContentLoaded', function() {
|
||||||
|
console.log('DOM loaded, setting up admin modal...');
|
||||||
|
|
||||||
const addAdminBtn = document.querySelector('.btn-primary');
|
const addAdminBtn = document.querySelector('.btn-primary');
|
||||||
|
const adminForm = document.getElementById('adminForm');
|
||||||
|
|
||||||
|
if (addAdminBtn) {
|
||||||
|
console.log('Add admin button found');
|
||||||
addAdminBtn.addEventListener('click', function() {
|
addAdminBtn.addEventListener('click', function() {
|
||||||
// In a real application, this would open a modal
|
console.log('Add admin button clicked');
|
||||||
alert('Modal tambah admin akan dibuka di sini');
|
openModal();
|
||||||
});
|
});
|
||||||
|
} else {
|
||||||
// Edit buttons
|
console.error('Add admin button not found');
|
||||||
document.querySelectorAll('.btn-action.text-blue-600').forEach(btn => {
|
|
||||||
btn.addEventListener('click', function() {
|
|
||||||
// In a real application, this would open edit modal
|
|
||||||
alert('Modal edit admin akan dibuka di sini');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
// Delete buttons
|
|
||||||
document.querySelectorAll('.btn-action.text-red-600').forEach(btn => {
|
|
||||||
btn.addEventListener('click', function() {
|
|
||||||
// In a real application, this would show confirmation dialog
|
|
||||||
if(confirm('Apakah Anda yakin ingin menghapus admin ini?')) {
|
|
||||||
alert('Admin akan dihapus');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (adminForm) {
|
||||||
|
console.log('Admin form found, setting up submit handler');
|
||||||
|
adminForm.addEventListener('submit', function(e) {
|
||||||
|
console.log('Form submit event triggered');
|
||||||
|
saveAdmin(e);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
console.error('Admin form not found');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Setup action buttons
|
||||||
|
const editButtons = document.querySelectorAll('[onclick*="editAdmin"]');
|
||||||
|
const deleteButtons = document.querySelectorAll('[onclick*="deleteAdmin"]');
|
||||||
|
|
||||||
|
console.log('Action buttons found:', {
|
||||||
|
edit: editButtons.length,
|
||||||
|
delete: deleteButtons.length
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
function openModal(adminId = null) {
|
||||||
|
const modal = document.getElementById('adminModal');
|
||||||
|
const form = document.getElementById('adminForm');
|
||||||
|
const title = document.getElementById('modalTitle');
|
||||||
|
|
||||||
|
form.reset();
|
||||||
|
document.getElementById('adminId').value = adminId || '';
|
||||||
|
|
||||||
|
if (adminId) {
|
||||||
|
title.textContent = 'Edit Admin';
|
||||||
|
// Load admin data
|
||||||
|
fetch(`/admin/manage-admin/${adminId}/edit`)
|
||||||
|
.then(response => response.json())
|
||||||
|
.then(data => {
|
||||||
|
document.getElementById('name').value = data.name;
|
||||||
|
document.getElementById('email').value = data.email;
|
||||||
|
document.getElementById('role').value = data.role;
|
||||||
|
document.getElementById('password').removeAttribute('required');
|
||||||
|
})
|
||||||
|
.catch(error => {
|
||||||
|
console.error('Error:', error);
|
||||||
|
alert('Gagal memuat data admin');
|
||||||
});
|
});
|
||||||
|
} else {
|
||||||
|
title.textContent = 'Tambah Admin';
|
||||||
|
document.getElementById('password').setAttribute('required', 'required');
|
||||||
|
}
|
||||||
|
|
||||||
|
modal.classList.remove('hidden');
|
||||||
|
}
|
||||||
|
|
||||||
|
function closeModal() {
|
||||||
|
document.getElementById('adminModal').classList.add('hidden');
|
||||||
|
document.getElementById('adminForm').reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
function saveAdmin(event) {
|
||||||
|
event.preventDefault();
|
||||||
|
|
||||||
|
const formData = new FormData(event.target);
|
||||||
|
const adminId = formData.get('id');
|
||||||
|
const submitBtn = event.target.querySelector('button[type="submit"]');
|
||||||
|
|
||||||
|
// Show loading state
|
||||||
|
const originalText = submitBtn.innerHTML;
|
||||||
|
submitBtn.innerHTML = '<i class="fas fa-spinner fa-spin mr-2"></i>Menyimpan...';
|
||||||
|
submitBtn.disabled = true;
|
||||||
|
|
||||||
|
const url = adminId ? `/admin/manage-admin/${adminId}` : '/admin/manage-admin';
|
||||||
|
const method = adminId ? 'PUT' : 'POST';
|
||||||
|
|
||||||
|
// Convert FormData to object for JSON
|
||||||
|
const data = Object.fromEntries(formData.entries());
|
||||||
|
console.log('Data being sent:', data); // Debug log
|
||||||
|
delete data.id; // Remove id from data
|
||||||
|
|
||||||
|
fetch(url, {
|
||||||
|
method: method,
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
'X-CSRF-TOKEN': document.querySelector('meta[name="csrf-token"]').getAttribute('content')
|
||||||
|
},
|
||||||
|
body: JSON.stringify(data)
|
||||||
|
})
|
||||||
|
.then(response => {
|
||||||
|
if (!response.ok) {
|
||||||
|
throw new Error('Network response was not ok');
|
||||||
|
}
|
||||||
|
return response.json();
|
||||||
|
})
|
||||||
|
.then(data => {
|
||||||
|
if (data.errors) {
|
||||||
|
// Handle validation errors
|
||||||
|
let errorMessages = '';
|
||||||
|
for (const field in data.errors) {
|
||||||
|
errorMessages += data.errors[field].join('\n') + '\n';
|
||||||
|
}
|
||||||
|
alert('Validation Error:\n' + errorMessages);
|
||||||
|
} else {
|
||||||
|
alert(data.success || 'Admin berhasil disimpan!');
|
||||||
|
closeModal();
|
||||||
|
location.reload(); // Reload to show updated data
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch(error => {
|
||||||
|
console.error('Error:', error);
|
||||||
|
alert('Terjadi kesalahan. Silakan coba lagi.\nError: ' + error.message);
|
||||||
|
})
|
||||||
|
.finally(() => {
|
||||||
|
// Reset button state
|
||||||
|
submitBtn.innerHTML = originalText;
|
||||||
|
submitBtn.disabled = false;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function editAdmin(id) {
|
||||||
|
console.log('Edit admin clicked for ID:', id);
|
||||||
|
openModal(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
function deleteAdmin(id) {
|
||||||
|
console.log('Delete admin clicked for ID:', id);
|
||||||
|
if (confirm('Apakah Anda yakin ingin menghapus admin ini?')) {
|
||||||
|
fetch(`/admin/manage-admin/${id}`, {
|
||||||
|
method: 'DELETE',
|
||||||
|
headers: {
|
||||||
|
'X-CSRF-TOKEN': document.querySelector('meta[name="csrf-token"]').getAttribute('content')
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.then(response => response.json())
|
||||||
|
.then(data => {
|
||||||
|
if (data.error) {
|
||||||
|
alert(data.error);
|
||||||
|
} else {
|
||||||
|
location.reload();
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch(error => {
|
||||||
|
console.error('Error:', error);
|
||||||
|
alert('Terjadi kesalahan. Silakan coba lagi.');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
@endsection
|
@endsection
|
||||||
|
|
|
||||||
|
|
@ -13,25 +13,25 @@
|
||||||
<!-- Navigation Menu -->
|
<!-- Navigation Menu -->
|
||||||
<nav class="flex-1 p-4 space-y-2">
|
<nav class="flex-1 p-4 space-y-2">
|
||||||
<a href="{{ route('admin.dashboard') }}"
|
<a href="{{ route('admin.dashboard') }}"
|
||||||
class="sidebar-item flex items-center space-x-3 px-4 py-3 rounded-lg text-gray-700 hover:bg-gray-50 transition-all {{ request()->routeIs('admin.dashboard') ? 'active' : '' }}">
|
class="sidebar-link flex items-center space-x-3 px-4 py-3 rounded-lg text-gray-700 hover:bg-gray-50 transition-all {{ request()->routeIs('admin.dashboard') ? 'active' : '' }}">
|
||||||
<i class="fas fa-home w-5"></i>
|
<i class="fas fa-home w-5"></i>
|
||||||
<span>Dashboard</span>
|
<span>Dashboard</span>
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
<a href="{{ route('admin.manage-admin') }}"
|
<a href="{{ route('admin.manage-admin') }}"
|
||||||
class="sidebar-item flex items-center space-x-3 px-4 py-3 rounded-lg text-gray-700 hover:bg-gray-50 transition-all {{ request()->routeIs('admin.manage-admin') ? 'active' : '' }}">
|
class="sidebar-link flex items-center space-x-3 px-4 py-3 rounded-lg text-gray-700 hover:bg-gray-50 transition-all {{ request()->routeIs('admin.manage-admin') ? 'active' : '' }}">
|
||||||
<i class="fas fa-users w-5"></i>
|
<i class="fas fa-users w-5"></i>
|
||||||
<span>Kelola Akun Admin</span>
|
<span>Kelola Akun Admin</span>
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
<a href="{{ route('admin.classification-history') }}"
|
<a href="{{ route('admin.classification-history') }}"
|
||||||
class="sidebar-item flex items-center space-x-3 px-4 py-3 rounded-lg text-gray-700 hover:bg-gray-50 transition-all {{ request()->routeIs('admin.classification-history') ? 'active' : '' }}">
|
class="sidebar-link flex items-center space-x-3 px-4 py-3 rounded-lg text-gray-700 hover:bg-gray-50 transition-all {{ request()->routeIs('admin.classification-history') ? 'active' : '' }}">
|
||||||
<i class="fas fa-history w-5"></i>
|
<i class="fas fa-history w-5"></i>
|
||||||
<span>Riwayat Klasifikasi</span>
|
<span>Riwayat Klasifikasi</span>
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
<a href="{{ route('admin.system-statistics') }}"
|
<a href="{{ route('admin.system-statistics') }}"
|
||||||
class="sidebar-item flex items-center space-x-3 px-4 py-3 rounded-lg text-gray-700 hover:bg-gray-50 transition-all {{ request()->routeIs('admin.system-statistics') ? 'active' : '' }}">
|
class="sidebar-link flex items-center space-x-3 px-4 py-3 rounded-lg text-gray-700 hover:bg-gray-50 transition-all {{ request()->routeIs('admin.system-statistics') ? 'active' : '' }}">
|
||||||
<i class="fas fa-chart-bar w-5"></i>
|
<i class="fas fa-chart-bar w-5"></i>
|
||||||
<span>Statistik Sistem</span>
|
<span>Statistik Sistem</span>
|
||||||
</a>
|
</a>
|
||||||
|
|
|
||||||
|
|
@ -22,15 +22,15 @@
|
||||||
<div class="flex justify-between items-center h-16">
|
<div class="flex justify-between items-center h-16">
|
||||||
<div class="flex items-center">
|
<div class="flex items-center">
|
||||||
<div class="flex-shrink-0">
|
<div class="flex-shrink-0">
|
||||||
<span class="text-2xl font-bold text-red-600">🍅 MaturityScan</span>
|
<span class="text-2xl font-bold text-red-600">MaturityScan</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="hidden md:block">
|
<div class="hidden md:block">
|
||||||
<div class="ml-10 flex items-baseline space-x-4">
|
<div class="ml-10 flex items-baseline space-x-4">
|
||||||
<a href="#" class="text-gray-900 hover:text-red-600 px-3 py-2 rounded-md text-sm font-medium transition-colors">Beranda</a>
|
<a href="#" class="text-gray-900 hover:text-red-600 px-3 py-2 rounded-md text-sm font-medium transition-colors">Beranda</a>
|
||||||
<a href="{{ route('about') }}"class="text-gray-500 hover:text-red-600 px-3 py-2 rounded-md text-sm font-medium transition-colors">Tentang kami</a>
|
<a href="{{ route('about') }}"class="text-gray-500 hover:text-red-600 px-3 py-2 rounded-md text-sm font-medium transition-colors">Tentang kami</a>
|
||||||
<a href="{{ route('login') }}" class="bg-red-600 hover:bg-red-700 text-white px-4 py-2 rounded-md text-sm font-medium transition-colors">
|
<a href="{{ route('login') }}" class="bg-red-600 hover:bg-red-700 text-white font-semibold py-2 px-6 rounded-lg transition-colors">
|
||||||
<i class="fas fa-sign-in-alt mr-2"></i>Login
|
Login
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -58,7 +58,7 @@
|
||||||
</p>
|
</p>
|
||||||
<div class="flex flex-col sm:flex-row gap-4 justify-center lg:justify-start">
|
<div class="flex flex-col sm:flex-row gap-4 justify-center lg:justify-start">
|
||||||
<a href="{{ route('upload.index') }}" class="bg-red-600 hover:bg-red-700 text-white font-semibold py-3 px-8 rounded-lg shadow-lg transform hover:scale-105 transition-all duration-200 inline-block text-center">
|
<a href="{{ route('upload.index') }}" class="bg-red-600 hover:bg-red-700 text-white font-semibold py-3 px-8 rounded-lg shadow-lg transform hover:scale-105 transition-all duration-200 inline-block text-center">
|
||||||
📤 Unggah Gambar Tomat
|
Unggah Gambar Tomat
|
||||||
</a>
|
</a>
|
||||||
<a href="{{ route('about') }}" class="bg-white hover:bg-gray-50 text-gray-700 font-semibold py-3 px-8 rounded-lg shadow-md border border-gray-200 transition-all duration-200 inline-block text-center">
|
<a href="{{ route('about') }}" class="bg-white hover:bg-gray-50 text-gray-700 font-semibold py-3 px-8 rounded-lg shadow-md border border-gray-200 transition-all duration-200 inline-block text-center">
|
||||||
Pelajari Lebih Lanjut
|
Pelajari Lebih Lanjut
|
||||||
|
|
@ -72,7 +72,7 @@
|
||||||
class="rounded-lg shadow-md w-full h-auto">
|
class="rounded-lg shadow-md w-full h-auto">
|
||||||
</div>
|
</div>
|
||||||
<div class="absolute -bottom-4 -right-4 bg-yellow-400 text-yellow-900 px-4 py-2 rounded-full font-semibold text-sm shadow-lg">
|
<div class="absolute -bottom-4 -right-4 bg-yellow-400 text-yellow-900 px-4 py-2 rounded-full font-semibold text-sm shadow-lg">
|
||||||
🌟 Akurasi 95%
|
<i class="fas fa-star mr-2"></i>Akurasi 95%
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -90,7 +90,7 @@ class="rounded-lg shadow-md w-full h-auto">
|
||||||
<!-- Mentah Card -->
|
<!-- Mentah Card -->
|
||||||
<div class="bg-green-50 border-2 border-green-200 rounded-xl p-8 text-center hover:shadow-xl transition-all duration-300 transform hover:-translate-y-2">
|
<div class="bg-green-50 border-2 border-green-200 rounded-xl p-8 text-center hover:shadow-xl transition-all duration-300 transform hover:-translate-y-2">
|
||||||
<div class="w-20 h-20 bg-green-500 rounded-full mx-auto mb-6 flex items-center justify-center">
|
<div class="w-20 h-20 bg-green-500 rounded-full mx-auto mb-6 flex items-center justify-center">
|
||||||
<span class="text-3xl">🍃</span>
|
<i class="fas fa-leaf text-3xl text-green-200"></i>
|
||||||
</div>
|
</div>
|
||||||
<h3 class="text-2xl font-bold text-green-800 mb-4">Mentah</h3>
|
<h3 class="text-2xl font-bold text-green-800 mb-4">Mentah</h3>
|
||||||
<p class="text-gray-600 mb-4">Tomat yang belum matang sempurna, berwarna hijau dan tekstur masih keras.</p>
|
<p class="text-gray-600 mb-4">Tomat yang belum matang sempurna, berwarna hijau dan tekstur masih keras.</p>
|
||||||
|
|
@ -102,7 +102,7 @@ class="rounded-lg shadow-md w-full h-auto">
|
||||||
<!-- Setengah Matang Card -->
|
<!-- Setengah Matang Card -->
|
||||||
<div class="bg-yellow-50 border-2 border-yellow-200 rounded-xl p-8 text-center hover:shadow-xl transition-all duration-300 transform hover:-translate-y-2">
|
<div class="bg-yellow-50 border-2 border-yellow-200 rounded-xl p-8 text-center hover:shadow-xl transition-all duration-300 transform hover:-translate-y-2">
|
||||||
<div class="w-20 h-20 bg-yellow-500 rounded-full mx-auto mb-6 flex items-center justify-center">
|
<div class="w-20 h-20 bg-yellow-500 rounded-full mx-auto mb-6 flex items-center justify-center">
|
||||||
<span class="text-3xl">🟡</span>
|
<i class="fas fa-circle-half-stroke text-3xl text-yellow-200"></i>
|
||||||
</div>
|
</div>
|
||||||
<h3 class="text-2xl font-bold text-yellow-800 mb-4">Setengah Matang</h3>
|
<h3 class="text-2xl font-bold text-yellow-800 mb-4">Setengah Matang</h3>
|
||||||
<p class="text-gray-600 mb-4">Tomat dalam proses pematangan, perpaduan warna hijau dan merah.</p>
|
<p class="text-gray-600 mb-4">Tomat dalam proses pematangan, perpaduan warna hijau dan merah.</p>
|
||||||
|
|
@ -114,7 +114,7 @@ class="rounded-lg shadow-md w-full h-auto">
|
||||||
<!-- Matang Card -->
|
<!-- Matang Card -->
|
||||||
<div class="bg-red-50 border-2 border-red-200 rounded-xl p-8 text-center hover:shadow-xl transition-all duration-300 transform hover:-translate-y-2">
|
<div class="bg-red-50 border-2 border-red-200 rounded-xl p-8 text-center hover:shadow-xl transition-all duration-300 transform hover:-translate-y-2">
|
||||||
<div class="w-20 h-20 bg-red-500 rounded-full mx-auto mb-6 flex items-center justify-center">
|
<div class="w-20 h-20 bg-red-500 rounded-full mx-auto mb-6 flex items-center justify-center">
|
||||||
<span class="text-3xl">🍅</span>
|
<i class="fas fa-circle text-3xl text-red-200"></i>
|
||||||
</div>
|
</div>
|
||||||
<h3 class="text-2xl font-bold text-red-800 mb-4">Matang</h3>
|
<h3 class="text-2xl font-bold text-red-800 mb-4">Matang</h3>
|
||||||
<p class="text-gray-600 mb-4">Tomat matang sempurna, berwarna merah cerah dan tekstur lembut.</p>
|
<p class="text-gray-600 mb-4">Tomat matang sempurna, berwarna merah cerah dan tekstur lembut.</p>
|
||||||
|
|
@ -138,7 +138,7 @@ class="rounded-lg shadow-md w-full h-auto">
|
||||||
<div class="relative">
|
<div class="relative">
|
||||||
<div class="bg-white rounded-xl p-8 shadow-lg hover:shadow-2xl transition-all duration-300 text-center">
|
<div class="bg-white rounded-xl p-8 shadow-lg hover:shadow-2xl transition-all duration-300 text-center">
|
||||||
<div class="w-16 h-16 bg-blue-500 rounded-full mx-auto mb-6 flex items-center justify-center">
|
<div class="w-16 h-16 bg-blue-500 rounded-full mx-auto mb-6 flex items-center justify-center">
|
||||||
<span class="text-2xl">📷</span>
|
<i class="fas fa-camera text-2xl text-white"></i>
|
||||||
</div>
|
</div>
|
||||||
<h3 class="text-xl font-bold text-gray-900 mb-4">Unggah Gambar</h3>
|
<h3 class="text-xl font-bold text-gray-900 mb-4">Unggah Gambar</h3>
|
||||||
<p class="text-gray-600">Ambil foto tomat atau unggah gambar dari galeri perangkat Anda.</p>
|
<p class="text-gray-600">Ambil foto tomat atau unggah gambar dari galeri perangkat Anda.</p>
|
||||||
|
|
@ -154,7 +154,7 @@ class="rounded-lg shadow-md w-full h-auto">
|
||||||
<div class="relative">
|
<div class="relative">
|
||||||
<div class="bg-white rounded-xl p-8 shadow-lg hover:shadow-2xl transition-all duration-300 text-center">
|
<div class="bg-white rounded-xl p-8 shadow-lg hover:shadow-2xl transition-all duration-300 text-center">
|
||||||
<div class="w-16 h-16 bg-purple-500 rounded-full mx-auto mb-6 flex items-center justify-center">
|
<div class="w-16 h-16 bg-purple-500 rounded-full mx-auto mb-6 flex items-center justify-center">
|
||||||
<span class="text-2xl">🤖</span>
|
<i class="fas fa-robot text-2xl text-white"></i>
|
||||||
</div>
|
</div>
|
||||||
<h3 class="text-xl font-bold text-gray-900 mb-4">Analisis AI</h3>
|
<h3 class="text-xl font-bold text-gray-900 mb-4">Analisis AI</h3>
|
||||||
<p class="text-gray-600">Sistem AI kami menganalisis warna, tekstur, dan bentuk tomat secara otomatis.</p>
|
<p class="text-gray-600">Sistem AI kami menganalisis warna, tekstur, dan bentuk tomat secara otomatis.</p>
|
||||||
|
|
@ -170,7 +170,7 @@ class="rounded-lg shadow-md w-full h-auto">
|
||||||
<div class="relative">
|
<div class="relative">
|
||||||
<div class="bg-white rounded-xl p-8 shadow-lg hover:shadow-2xl transition-all duration-300 text-center">
|
<div class="bg-white rounded-xl p-8 shadow-lg hover:shadow-2xl transition-all duration-300 text-center">
|
||||||
<div class="w-16 h-16 bg-green-500 rounded-full mx-auto mb-6 flex items-center justify-center">
|
<div class="w-16 h-16 bg-green-500 rounded-full mx-auto mb-6 flex items-center justify-center">
|
||||||
<span class="text-2xl">📊</span>
|
<i class="fas fa-chart-line text-2xl text-white"></i>
|
||||||
</div>
|
</div>
|
||||||
<h3 class="text-xl font-bold text-gray-900 mb-4">Dapatkan Hasil</h3>
|
<h3 class="text-xl font-bold text-gray-900 mb-4">Dapatkan Hasil</h3>
|
||||||
<p class="text-gray-600">Lihat hasil klasifikasi kematangan tomat dengan akurasi tinggi.</p>
|
<p class="text-gray-600">Lihat hasil klasifikasi kematangan tomat dengan akurasi tinggi.</p>
|
||||||
|
|
@ -208,16 +208,16 @@ class="rounded-lg shadow-md w-full h-auto">
|
||||||
<h3 class="text-lg font-semibold mb-4">Connect</h3>
|
<h3 class="text-lg font-semibold mb-4">Connect</h3>
|
||||||
<div class="flex space-x-4">
|
<div class="flex space-x-4">
|
||||||
<a href="#" class="w-10 h-10 bg-gray-800 rounded-full flex items-center justify-center hover:bg-gray-700 transition-colors">
|
<a href="#" class="w-10 h-10 bg-gray-800 rounded-full flex items-center justify-center hover:bg-gray-700 transition-colors">
|
||||||
<span class="text-lg">📘</span>
|
<i class="fab fa-facebook-f text-lg"></i>
|
||||||
</a>
|
</a>
|
||||||
<a href="#" class="w-10 h-10 bg-gray-800 rounded-full flex items-center justify-center hover:bg-gray-700 transition-colors">
|
<a href="#" class="w-10 h-10 bg-gray-800 rounded-full flex items-center justify-center hover:bg-gray-700 transition-colors">
|
||||||
<span class="text-lg">🐦</span>
|
<i class="fab fa-twitter text-lg"></i>
|
||||||
</a>
|
</a>
|
||||||
<a href="#" class="w-10 h-10 bg-gray-800 rounded-full flex items-center justify-center hover:bg-gray-700 transition-colors">
|
<a href="#" class="w-10 h-10 bg-gray-800 rounded-full flex items-center justify-center hover:bg-gray-700 transition-colors">
|
||||||
<span class="text-lg">📷</span>
|
<i class="fab fa-instagram text-lg"></i>
|
||||||
</a>
|
</a>
|
||||||
<a href="#" class="w-10 h-10 bg-gray-800 rounded-full flex items-center justify-center hover:bg-gray-700 transition-colors">
|
<a href="#" class="w-10 h-10 bg-gray-800 rounded-full flex items-center justify-center hover:bg-gray-700 transition-colors">
|
||||||
<span class="text-lg">💼</span>
|
<i class="fab fa-linkedin-in text-lg"></i>
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
<div class="mt-4">
|
<div class="mt-4">
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
use Illuminate\Support\Facades\Route;
|
use Illuminate\Support\Facades\Route;
|
||||||
use App\Http\Controllers\UploadController;
|
use App\Http\Controllers\UploadController;
|
||||||
|
use App\Http\Controllers\AdminController;
|
||||||
|
|
||||||
Route::get('/', function () {
|
Route::get('/', function () {
|
||||||
return view('welcome');
|
return view('welcome');
|
||||||
|
|
@ -37,13 +38,13 @@
|
||||||
return view('Admin.index');
|
return view('Admin.index');
|
||||||
})->name('admin.dashboard');
|
})->name('admin.dashboard');
|
||||||
|
|
||||||
// Manage admin route
|
// Manage admin routes
|
||||||
Route::get('/admin/manage-admin', function () {
|
Route::get('/admin/manage-admin', [AdminController::class, 'index'])->name('admin.manage-admin');
|
||||||
if (!session('admin_logged_in')) {
|
Route::post('/admin/manage-admin', [AdminController::class, 'store'])->name('admin.manage-admin.store');
|
||||||
return redirect()->route('admin.login')->with('error', 'Silakan login terlebih dahulu.');
|
Route::get('/admin/manage-admin/{id}/edit', [AdminController::class, 'edit'])->name('admin.manage-admin.edit');
|
||||||
}
|
Route::put('/admin/manage-admin/{id}', [AdminController::class, 'update'])->name('admin.manage-admin.update');
|
||||||
return view('Admin.manage-admin');
|
Route::delete('/admin/manage-admin/{id}', [AdminController::class, 'destroy'])->name('admin.manage-admin.destroy');
|
||||||
})->name('admin.manage-admin');
|
Route::patch('/admin/manage-admin/{id}/toggle-status', [AdminController::class, 'toggleStatus'])->name('admin.manage-admin.toggle-status');
|
||||||
|
|
||||||
// Classification history route
|
// Classification history route
|
||||||
Route::get('/admin/classification-history', function () {
|
Route::get('/admin/classification-history', function () {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue