MIF_E31220412/resources/views/layouts/admin.blade.php

257 lines
15 KiB
PHP

<!DOCTYPE html>
<html lang="id">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>@yield('title', 'INUFA Admin')</title>
<script src="https://cdn.tailwindcss.com"></script>
@stack('styles')
</head>
<body class="bg-gray-100">
<div class="flex h-screen">
<!-- Admin Sidebar -->
<div class="w-64 h-full bg-white shadow-md">
<!-- Logo -->
<div class="p-4 flex justify-center">
<img src="{{ asset('assets/images/logo.png') }}" alt="INUFA Logo" class="w-28 h-28 object-contain">
</div>
<!-- Admin Menu -->
<nav class="mt-4">
<a href="{{ route('admin.dashboard') }}" class="block py-3 px-4 text-gray-800 font-semibold mb-1 hover:bg-gray-100 {{ request()->routeIs('admin.dashboard') ? 'bg-blue-800 text-white' : '' }}">
<div class="flex items-center">
<svg class="w-5 h-5 mr-3" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M3 7v10a2 2 0 002 2h14a2 2 0 002-2V9a2 2 0 00-2-2H5a2 2 0 00-2-2z" />
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M8 5a2 2 0 012-2h4a2 2 0 012 2v2H8V5z" />
</svg>
Dashboard
</div>
</a>
<a href="{{ route('pengguna') }}" class="block py-3 px-4 text-gray-800 font-semibold mb-1 hover:bg-gray-100 {{ request()->routeIs('pengguna*') ? 'bg-blue-800 text-white' : '' }}">
<div class="flex items-center">
<svg class="w-5 h-5 mr-3" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" 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" />
</svg>
Manajemen User
</div>
</a>
<a href="{{ route('paket.index') }}" class="block py-3 px-4 text-gray-800 font-semibold mb-1 hover:bg-gray-100 {{ request()->routeIs('paket*') ? 'bg-blue-800 text-white' : '' }}">
<div class="flex items-center">
<svg class="w-5 h-5 mr-3" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 8h14M5 8a2 2 0 110-4h14a2 2 0 110 4M5 8v10a2 2 0 002 2h10a2 2 0 002-2V8m-9 4h4" />
</svg>
Manajemen Paket
</div>
</a>
<a href="{{ route('input-stock') }}" class="block py-3 px-4 text-gray-800 font-semibold mb-1 hover:bg-gray-100 {{ request()->routeIs('input-stock*') ? 'bg-blue-800 text-white' : '' }}">
<div class="flex items-center">
<svg class="w-5 h-5 mr-3" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M20 7l-8-4-8 4m16 0l-8 4m8-4v10l-8 4m0-10L4 7m8 4v10M4 7v10l8 4" />
</svg>
Manajemen Stock
</div>
</a>
<a href="{{ route('sewa.index') }}" class="block py-3 px-4 text-gray-800 font-semibold mb-1 hover:bg-gray-100 {{ request()->routeIs('sewa.*') ? 'bg-blue-800 text-white' : '' }}">
<div class="flex items-center">
<svg class="w-5 h-5 mr-3" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2" />
</svg>
Manajemen Sewa
</div>
</a>
<a href="{{ route('riwayat') }}" class="block py-3 px-4 text-gray-800 font-semibold mb-1 hover:bg-gray-100 {{ request()->routeIs('riwayat') ? 'bg-blue-800 text-white' : '' }}">
<div class="flex items-center">
<svg class="w-5 h-5 mr-3" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z" />
</svg>
Laporan
</div>
</a>
<a href="{{ route('admin.verifikasi.index') }}" class="block py-3 px-4 text-gray-800 font-semibold mb-1 hover:bg-gray-100 {{ request()->routeIs('admin.verifikasi.*') ? 'bg-blue-800 text-white' : '' }}">
<div class="flex items-center">
<svg class="w-5 h-5 mr-3" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z" />
</svg>
Verifikasi Pembayaran
</div>
</a>
<!-- Menu Pesanan Dibatalkan dengan styling khusus -->
<div class="border-t border-gray-200 my-2"></div>
<a href="{{ route('admin.cancelled-orders') }}" class="block py-3 px-4 text-gray-800 font-semibold mb-1 hover:bg-red-50 hover:text-red-700 {{ request()->routeIs('admin.cancelled-orders*') ? 'bg-red-100 text-red-700 border-r-4 border-red-500' : '' }}">
<div class="flex items-center justify-between">
<div class="flex items-center">
<svg class="w-5 h-5 mr-3" 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>
<span>Pesanan Dibatalkan</span>
</div>
<span id="cancelled-orders-badge" class="hidden bg-red-500 text-white text-xs rounded-full px-2 py-1 font-bold">0</span>
</div>
</a>
<a href="{{ route('contact.index') }}" class="block py-3 px-4 text-gray-800 font-semibold mb-1 hover:bg-gray-100 {{ request()->routeIs('contact.*') ? 'bg-blue-800 text-white' : '' }}">
<div class="flex items-center">
<svg class="w-5 h-5 mr-3" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M3 8l7.89 4.26a2 2 0 002.22 0L21 8M5 19h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v10a2 2 0 002 2z" />
</svg>
Kelola Kontak
</div>
</a>
</nav>
</div>
<!-- Main Content -->
<div class="flex-1 flex flex-col">
<!-- Header -->
<header class="bg-white shadow-sm py-4 px-6 flex justify-between items-center">
<div class="flex space-x-8">
<h1 class="text-xl font-bold text-gray-800">@yield('header', 'Admin Dashboard')</h1>
</div>
<div class="flex items-center space-x-4">
<!-- Notifikasi Pembatalan di Header -->
<a href="{{ route('admin.cancelled-orders') }}" class="relative flex items-center space-x-2 px-3 py-2 bg-red-50 hover:bg-red-100 rounded-lg transition-colors">
<svg class="w-5 h-5 text-red-600" 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>
<span class="text-red-700 font-medium">Pesanan Dibatalkan</span>
<span id="header-cancelled-badge" class="hidden absolute -top-1 -right-1 bg-red-500 text-white text-xs rounded-full px-2 py-1 font-bold">0</span>
</a>
<a href="{{ route('profile.index') }}" class="font-semibold text-gray-600 flex items-center space-x-2">
<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" viewBox="0 0 20 20" fill="currentColor">
<path fill-rule="evenodd" d="M10 9a3 3 0 100-6 3 3 0 000 6zm-7 9a7 7 0 1114 0H3z" clip-rule="evenodd" />
</svg>
<span>Profile</span>
</a>
<form action="{{ route('logout') }}" method="POST" class="inline">
@csrf
<button type="submit" class="font-semibold text-gray-600 flex items-center space-x-2 hover:text-gray-800">
<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" viewBox="0 0 20 20" fill="currentColor">
<path fill-rule="evenodd" d="M3 3a1 1 0 00-1 1v12a1 1 0 102 0V4a1 1 0 00-1-1zm10.293 9.293a1 1 0 001.414 1.414l3-3a1 1 0 000-1.414l-3-3a1 1 0 10-1.414 1.414L14.586 9H7a1 1 0 100 2h7.586l-1.293 1.293z" clip-rule="evenodd" />
</svg>
<span>Logout</span>
</button>
</form>
</div>
</header>
<!-- Content -->
<main class="flex-1 p-6 bg-gray-100 overflow-auto">
@if(session('success'))
<div class="bg-green-100 border-l-4 border-green-500 text-green-700 p-4 mb-4 rounded" role="alert">
<p>{{ session('success') }}</p>
</div>
@endif
@if(session('warning'))
<div class="bg-yellow-100 border-l-4 border-yellow-500 text-yellow-700 p-4 mb-4 rounded" role="alert">
<p>{{ session('warning') }}</p>
</div>
@endif
@if(session('error'))
<div class="bg-red-100 border-l-4 border-red-500 text-red-700 p-4 mb-4 rounded" role="alert">
<p>{{ session('error') }}</p>
</div>
@endif
@yield('content')
</main>
</div>
</div>
@stack('scripts')
<script>
// Notifikasi real-time untuk pesanan yang dibatalkan
function updateCancelledOrdersBadge() {
fetch('{{ route("admin.cancelled-orders.count") }}')
.then(response => response.json())
.then(data => {
const badge = document.getElementById('cancelled-orders-badge');
if (data.count > 0) {
badge.textContent = data.count;
badge.classList.remove('hidden');
} else {
badge.classList.add('hidden');
}
})
.catch(error => {
console.error('Error fetching cancelled orders count:', error);
});
}
// Update badge setiap 30 detik
setInterval(updateCancelledOrdersBadge, 30000);
// Update badge saat halaman dimuat
document.addEventListener('DOMContentLoaded', updateCancelledOrdersBadge);
</script>
<script>
// Notifikasi toast untuk pembatalan pesanan
let lastCancellationCount = 0;
function checkNewCancellations() {
fetch('{{ route("admin.recent-cancellations") }}')
.then(response => response.json())
.then(data => {
if (data.cancellations && data.cancellations.length > 0) {
const latestCancellation = data.cancellations[0];
// Tampilkan toast notifikasi
showToast(
'Pesanan Dibatalkan',
`${latestCancellation.user_name} membatalkan pesanan #${latestCancellation.id} (${latestCancellation.paket_name})`
);
}
})
.catch(error => {
console.error('Error checking cancellations:', error);
});
}
function showToast(title, message) {
document.getElementById('toast-title').textContent = title;
document.getElementById('toast-message').textContent = message;
document.getElementById('toast').classList.remove('hidden');
// Auto hide setelah 5 detik
setTimeout(hideToast, 5000);
}
function hideToast() {
document.getElementById('toast').classList.add('hidden');
}
// Check pembatalan baru setiap 60 detik
setInterval(checkNewCancellations, 60000);
// Check saat halaman dimuat
document.addEventListener('DOMContentLoaded', function() {
setTimeout(checkNewCancellations, 5000); // Check setelah 5 detik
});
</script>
<!-- Toast Notification -->
<div id="toast" class="fixed top-4 right-4 z-50 hidden">
<div class="bg-red-500 text-white px-6 py-4 rounded-lg shadow-lg max-w-sm">
<div class="flex items-center">
<svg class="w-5 h-5 mr-2" fill="currentColor" viewBox="0 0 20 20">
<path fill-rule="evenodd" d="M8.257 3.099c.765-1.36 2.722-1.36 3.486 0l5.58 9.92c.75 1.334-.213 2.98-1.742 2.98H4.42c-1.53 0-2.493-1.646-1.743-2.98l5.58-9.92zM11 13a1 1 0 11-2 0 1 1 0 012 0zm-1-8a1 1 0 00-1 1v3a1 1 0 002 0V6a1 1 0 00-1-1z" clip-rule="evenodd" />
</svg>
<div>
<h4 class="font-semibold" id="toast-title">Pesanan Dibatalkan</h4>
<p class="text-sm" id="toast-message">Ada pesanan baru yang dibatalkan oleh customer.</p>
</div>
<button onclick="hideToast()" class="ml-4 text-white hover:text-gray-200">
<svg class="w-4 h-4" fill="currentColor" viewBox="0 0 20 20">
<path fill-rule="evenodd" d="M4.293 4.293a1 1 0 011.414 0L10 8.586l4.293-4.293a1 1 0 111.414 1.414L11.414 10l4.293 4.293a1 1 0 01-1.414 1.414L10 11.414l-4.293 4.293a1 1 0 01-1.414-1.414L8.586 10 4.293 5.707a1 1 0 010-1.414z" clip-rule="evenodd" />
</svg>
</button>
</div>
</div>
</div>
</body>
</html>