Kelola Venue by Admin bisa, tapi bookingnya error lg

This commit is contained in:
Stephen Gesityan 2025-06-04 16:57:17 +07:00
parent 0580940cf5
commit 64951d2018
7 changed files with 589 additions and 40 deletions

View File

@ -0,0 +1,114 @@
<?php
namespace App\Http\Controllers\admin;
use App\Http\Controllers\Controller;
use App\Models\Venue;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Facades\Validator;
class VenueController extends Controller
{
/**
* Display venue management page for current admin
*/
public function index()
{
// Get current admin's venue
$venue = auth()->user()->venue;
if (!$venue) {
return redirect()->route('admin.dashboard')->with('error', 'Anda belum memiliki venue yang ditugaskan.');
}
return view('admin.venues.index', compact('venue'));
}
/**
* Show the form for editing venue
*/
public function edit()
{
$venue = auth()->user()->venue;
if (!$venue) {
return redirect()->route('admin.dashboard')->with('error', 'Anda belum memiliki venue yang ditugaskan.');
}
return view('admin.venues.edit', compact('venue'));
}
/**
* Update venue information
*/
public function update(Request $request)
{
$venue = auth()->user()->venue;
if (!$venue) {
return redirect()->route('admin.dashboard')->with('error', 'Anda belum memiliki venue yang ditugaskan.');
}
// Validation rules
$validator = Validator::make($request->all(), [
'name' => 'required|string|max:255',
'address' => 'required|string|max:500',
'phone' => 'nullable|string|max:20',
'description' => 'nullable|string|max:1000',
'open_time' => 'required|date_format:H:i',
'close_time' => 'required|date_format:H:i',
'image' => 'nullable|image|mimes:jpeg,png,jpg,gif|max:2048', // Max 2MB
], [
'name.required' => 'Nama venue harus diisi.',
'address.required' => 'Alamat venue harus diisi.',
'open_time.required' => 'Jam buka harus diisi.',
'open_time.date_format' => 'Format jam buka tidak valid (gunakan format HH:MM).',
'close_time.required' => 'Jam tutup harus diisi.',
'close_time.date_format' => 'Format jam tutup tidak valid (gunakan format HH:MM).',
'image.image' => 'File yang diupload harus berupa gambar.',
'image.mimes' => 'Gambar harus berformat: jpeg, png, jpg, atau gif.',
'image.max' => 'Ukuran gambar maksimal 2MB.',
]);
if ($validator->fails()) {
return redirect()->back()
->withErrors($validator)
->withInput();
}
try {
// Handle image upload
$imagePath = $venue->image; // Keep current image by default
if ($request->hasFile('image')) {
// Delete old image if exists
if ($venue->image && Storage::disk('public')->exists($venue->image)) {
Storage::disk('public')->delete($venue->image);
}
// Store new image
$imagePath = $request->file('image')->store('venues', 'public');
}
// Update venue data
$venue->update([
'name' => $request->name,
'address' => $request->address,
'phone' => $request->phone,
'description' => $request->description,
'open_time' => $request->open_time,
'close_time' => $request->close_time,
'image' => $imagePath,
]);
return redirect()->route('admin.venue.index')
->with('success', 'Informasi venue berhasil diperbarui!');
} catch (\Exception $e) {
return redirect()->back()
->with('error', 'Terjadi kesalahan saat memperbarui venue: ' . $e->getMessage())
->withInput();
}
}
}

View File

@ -9,7 +9,20 @@ class Venue extends Model
{
use HasFactory;
protected $fillable = ['name', 'location', 'address', 'image'];
protected $fillable = [
'name',
'address',
'image',
'phone', // Pastikan field ini ada
'description', // Pastikan field ini ada
'open_time', // Pastikan field ini ada
'close_time', // Pastikan field ini ada
];
protected $casts = [
'open_time' => 'datetime',
'close_time' => 'datetime',
];
public function tables()
{

View File

@ -0,0 +1,206 @@
@extends('layouts.admin')
@section('content')
<div class="p-6">
<!-- Header -->
<div class="mb-6">
<div class="flex items-center space-x-4">
<a href="{{ route('admin.venue.index') }}" class="text-gray-500 hover:text-gray-700">
<svg xmlns="http://www.w3.org/2000/svg" class="h-6 w-6" fill="none" viewBox="0 0 24 24"
stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 19l-7-7 7-7" />
</svg>
</a>
<div>
<h1 class="text-2xl font-bold text-gray-900">Edit Venue</h1>
<p class="text-gray-600 mt-1">Perbarui informasi venue Anda</p>
</div>
</div>
</div>
<!-- Alert Messages -->
@if(session('success'))
<div class="mb-6 bg-green-100 border border-green-400 text-green-700 px-4 py-3 rounded-lg">
{{ session('success') }}
</div>
@endif
@if(session('error'))
<div class="mb-6 bg-red-100 border border-red-400 text-red-700 px-4 py-3 rounded-lg">
{{ session('error') }}
</div>
@endif
<!-- Edit Form -->
<div class="bg-white rounded-lg shadow-sm border border-gray-200">
<form action="{{ route('admin.venue.update') }}" method="POST" enctype="multipart/form-data" class="p-6">
@csrf
@method('PUT')
<div class="grid grid-cols-1 lg:grid-cols-2 gap-6">
<!-- Left Column -->
<div class="space-y-6">
<!-- Venue Name -->
<div>
<label for="name" class="block text-sm font-medium text-gray-700 mb-2">
Nama Venue <span class="text-red-500">*</span>
</label>
<input type="text" id="name" name="name" value="{{ old('name', $venue->name) }}"
class="w-full px-3 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500 @error('name') border-red-500 @enderror"
placeholder="Masukkan nama venue">
@error('name')
<p class="mt-1 text-sm text-red-600">{{ $message }}</p>
@enderror
</div>
<!-- Address -->
<div>
<label for="address" class="block text-sm font-medium text-gray-700 mb-2">
Alamat <span class="text-red-500">*</span>
</label>
<textarea id="address" name="address" rows="3"
class="w-full px-3 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500 @error('address') border-red-500 @enderror"
placeholder="Masukkan alamat lengkap venue">{{ old('address', $venue->address) }}</textarea>
@error('address')
<p class="mt-1 text-sm text-red-600">{{ $message }}</p>
@enderror
</div>
<!-- Phone -->
<div>
<label for="phone" class="block text-sm font-medium text-gray-700 mb-2">
Nomor Telepon
</label>
<input type="text" id="phone" name="phone" value="{{ old('phone', $venue->phone) }}"
class="w-full px-3 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500 @error('phone') border-red-500 @enderror"
placeholder="Contoh: 08123456789">
@error('phone')
<p class="mt-1 text-sm text-red-600">{{ $message }}</p>
@enderror
</div>
<!-- Operating Hours -->
<div class="grid grid-cols-2 gap-4">
<div>
<label for="open_time" class="block text-sm font-medium text-gray-700 mb-2">
Jam Buka <span class="text-red-500">*</span>
</label>
<input type="time" id="open_time" name="open_time"
value="{{ old('open_time', $venue->open_time ? \Carbon\Carbon::parse($venue->open_time)->format('H:i') : '') }}"
class="w-full px-3 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500 @error('open_time') border-red-500 @enderror">
@error('open_time')
<p class="mt-1 text-sm text-red-600">{{ $message }}</p>
@enderror
</div>
<div>
<label for="close_time" class="block text-sm font-medium text-gray-700 mb-2">
Jam Tutup <span class="text-red-500">*</span>
</label>
<input type="time" id="close_time" name="close_time"
value="{{ old('close_time', $venue->close_time ? \Carbon\Carbon::parse($venue->close_time)->format('H:i') : '') }}"
class="w-full px-3 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500 @error('close_time') border-red-500 @enderror">
@error('close_time')
<p class="mt-1 text-sm text-red-600">{{ $message }}</p>
@enderror
</div>
</div>
</div>
<!-- Right Column -->
<div class="space-y-6">
<!-- Current Image -->
<div>
<label class="block text-sm font-medium text-gray-700 mb-2">
Foto Venue Saat Ini
</label>
<div class="w-full h-48 bg-gray-100 rounded-lg overflow-hidden">
@if($venue->image)
<img id="current-image" src="{{ asset('storage/' . $venue->image) }}"
alt="{{ $venue->name }}" class="w-full h-full object-cover">
@else
<div class="w-full h-full flex items-center justify-center text-gray-400">
<svg xmlns="http://www.w3.org/2000/svg" class="h-12 w-12" fill="none"
viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
d="M4 16l4.586-4.586a2 2 0 012.828 0L16 16m-2-2l1.586-1.586a2 2 0 012.828 0L20 14m-6-6h.01M6 20h12a2 2 0 002-2V6a2 2 0 00-2-2H6a2 2 0 00-2 2v12a2 2 0 002 2z" />
</svg>
</div>
@endif
</div>
</div>
<!-- New Image Upload -->
<div>
<label for="image" class="block text-sm font-medium text-gray-700 mb-2">
Upload Foto Baru (Opsional)
</label>
<input type="file" id="image" name="image" accept="image/*" onchange="previewImage(this)"
class="w-full px-3 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500 @error('image') border-red-500 @enderror">
@error('image')
<p class="mt-1 text-sm text-red-600">{{ $message }}</p>
@enderror
<p class="text-xs text-gray-500 mt-1">Format: JPEG, PNG, JPG, GIF. Maksimal 2MB</p>
<!-- Image Preview -->
<div id="image-preview" class="mt-4 hidden">
<p class="text-sm font-medium text-gray-700 mb-2">Preview Foto Baru:</p>
<div class="w-full h-48 bg-gray-100 rounded-lg overflow-hidden">
<img id="preview-img" src="" alt="Preview" class="w-full h-full object-cover">
</div>
</div>
</div>
</div>
</div>
<!-- Description -->
<div class="mt-6">
<label for="description" class="block text-sm font-medium text-gray-700 mb-2">
Deskripsi Venue
</label>
<textarea id="description" name="description" rows="4"
class="w-full px-3 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500 @error('description') border-red-500 @enderror"
placeholder="Masukkan deskripsi venue (fasilitas, suasana, dll)">{{ old('description', $venue->description) }}</textarea>
@error('description')
<p class="mt-1 text-sm text-red-600">{{ $message }}</p>
@enderror
</div>
<!-- Action Buttons -->
<div class="flex items-center justify-end space-x-4 mt-8 pt-6 border-t border-gray-200">
<a href="{{ route('admin.venue.index') }}"
class="px-4 py-2 text-gray-700 bg-gray-100 hover:bg-gray-200 rounded-lg font-medium transition-colors">
Batal
</a>
<button type="submit"
class="px-6 py-2 bg-blue-600 hover:bg-blue-700 text-white rounded-lg font-medium transition-colors">
<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5 inline mr-2" fill="none" viewBox="0 0 24 24"
stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 13l4 4L19 7" />
</svg>
Simpan Perubahan
</button>
</div>
</form>
</div>
</div>
<script>
function previewImage(input) {
const preview = document.getElementById('image-preview');
const previewImg = document.getElementById('preview-img');
if (input.files && input.files[0]) {
const reader = new FileReader();
reader.onload = function (e) {
previewImg.src = e.target.result;
preview.classList.remove('hidden');
}
reader.readAsDataURL(input.files[0]);
} else {
preview.classList.add('hidden');
}
}
</script>
@endsection

View File

@ -0,0 +1,197 @@
@extends('layouts.admin')
@section('content')
<div class="p-6">
<!-- Header -->
<div class="mb-6">
<div class="flex items-center justify-between">
<div>
<h1 class="text-2xl font-bold text-gray-900">Kelola Venue</h1>
<p class="text-gray-600 mt-1">Kelola informasi venue Anda</p>
</div>
<a href="{{ route('admin.venue.edit') }}"
class="bg-blue-600 hover:bg-blue-700 text-white px-4 py-2 rounded-lg font-medium transition-colors">
<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5 inline mr-2" fill="none" viewBox="0 0 24 24"
stroke="currentColor">
<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>
Edit Venue
</a>
</div>
</div>
<!-- Alert Messages -->
@if(session('success'))
<div class="mb-6 bg-green-100 border border-green-400 text-green-700 px-4 py-3 rounded-lg">
{{ session('success') }}
</div>
@endif
@if(session('error'))
<div class="mb-6 bg-red-100 border border-red-400 text-red-700 px-4 py-3 rounded-lg">
{{ session('error') }}
</div>
@endif
<!-- Venue Information Card -->
<div class="bg-white rounded-lg shadow-sm border border-gray-200">
<div class="p-6">
<div class="grid grid-cols-1 lg:grid-cols-3 gap-6">
<!-- Venue Image -->
<div class="lg:col-span-1">
<h3 class="text-lg font-semibold text-gray-900 mb-4">Foto Venue</h3>
<div class="aspect-w-16 aspect-h-9 rounded-lg overflow-hidden bg-gray-100">
@if($venue->image)
<img src="{{ asset('storage/' . $venue->image) }}" alt="{{ $venue->name }}"
class="w-full h-48 object-cover rounded-lg">
@else
<div class="w-full h-48 bg-gray-200 rounded-lg flex items-center justify-center">
<svg xmlns="http://www.w3.org/2000/svg" class="h-12 w-12 text-gray-400" fill="none"
viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
d="M4 16l4.586-4.586a2 2 0 012.828 0L16 16m-2-2l1.586-1.586a2 2 0 012.828 0L20 14m-6-6h.01M6 20h12a2 2 0 002-2V6a2 2 0 00-2-2H6a2 2 0 00-2 2v12a2 2 0 002 2z" />
</svg>
</div>
@endif
</div>
</div>
<!-- Venue Details -->
<div class="lg:col-span-2">
<h3 class="text-lg font-semibold text-gray-900 mb-4">Informasi Venue</h3>
<div class="space-y-4">
<!-- Venue Name -->
<div class="flex items-start">
<div class="flex-shrink-0 w-32">
<span class="text-sm font-medium text-gray-500">Nama Venue:</span>
</div>
<div class="flex-1">
<span class="text-sm text-gray-900 font-medium">{{ $venue->name }}</span>
</div>
</div>
<!-- Address -->
<div class="flex items-start">
<div class="flex-shrink-0 w-32">
<span class="text-sm font-medium text-gray-500">Alamat:</span>
</div>
<div class="flex-1">
<span class="text-sm text-gray-900">{{ $venue->address }}</span>
</div>
</div>
<!-- Phone -->
<div class="flex items-start">
<div class="flex-shrink-0 w-32">
<span class="text-sm font-medium text-gray-500">Telepon:</span>
</div>
<div class="flex-1">
<span class="text-sm text-gray-900">{{ $venue->phone ?: '-' }}</span>
</div>
</div>
<!-- Operating Hours -->
<div class="flex items-start">
<div class="flex-shrink-0 w-32">
<span class="text-sm font-medium text-gray-500">Jam Operasional:</span>
</div>
<div class="flex-1">
<span class="text-sm text-gray-900">
{{ $venue->open_time ? \Carbon\Carbon::parse($venue->open_time)->format('H:i') : '-' }}
-
{{ $venue->close_time ? \Carbon\Carbon::parse($venue->close_time)->format('H:i') : '-' }}
</span>
</div>
</div>
<!-- Description -->
<div class="flex items-start">
<div class="flex-shrink-0 w-32">
<span class="text-sm font-medium text-gray-500">Deskripsi:</span>
</div>
<div class="flex-1">
<p class="text-sm text-gray-900">{{ $venue->description ?: 'Belum ada deskripsi' }}</p>
</div>
</div>
<!-- Last Updated -->
<div class="flex items-start">
<div class="flex-shrink-0 w-32">
<span class="text-sm font-medium text-gray-500">Terakhir Diperbarui:</span>
</div>
<div class="flex-1">
<span
class="text-sm text-gray-900">{{ $venue->updated_at->format('d M Y, H:i') }}</span>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- Statistics Cards -->
<div class="grid grid-cols-1 md:grid-cols-3 gap-4 mt-6">
<!-- Total Tables -->
<div class="bg-white p-6 rounded-lg shadow-sm border border-gray-200">
<div class="flex items-center">
<div class="flex-shrink-0">
<div class="w-8 h-8 bg-blue-100 rounded-full flex items-center justify-center">
<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5 text-blue-600" fill="none"
viewBox="0 0 24 24" stroke="currentColor">
<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" />
</svg>
</div>
</div>
<div class="ml-4">
<p class="text-sm font-medium text-gray-500">Total Meja</p>
<p class="text-2xl font-semibold text-gray-900">{{ $venue->tables->count() }}</p>
</div>
</div>
</div>
<!-- Available Tables -->
<div class="bg-white p-6 rounded-lg shadow-sm border border-gray-200">
<div class="flex items-center">
<div class="flex-shrink-0">
<div class="w-8 h-8 bg-green-100 rounded-full flex items-center justify-center">
<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5 text-green-600" fill="none"
viewBox="0 0 24 24" stroke="currentColor">
<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>
</div>
</div>
<div class="ml-4">
<p class="text-sm font-medium text-gray-500">Meja Tersedia</p>
<p class="text-2xl font-semibold text-gray-900">
{{ $venue->tables->where('status', 'available')->count() }}</p>
</div>
</div>
</div>
<!-- Occupied Tables -->
<div class="bg-white p-6 rounded-lg shadow-sm border border-gray-200">
<div class="flex items-center">
<div class="flex-shrink-0">
<div class="w-8 h-8 bg-red-100 rounded-full flex items-center justify-center">
<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5 text-red-600" fill="none"
viewBox="0 0 24 24" stroke="currentColor">
<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" />
</svg>
</div>
</div>
<div class="ml-4">
<p class="text-sm font-medium text-gray-500">Meja Terpakai</p>
<p class="text-2xl font-semibold text-gray-900">
{{ $venue->tables->where('status', 'occupied')->count() }}</p>
</div>
</div>
</div>
</div>
</div>
@endsection

View File

@ -97,6 +97,16 @@ class="nav-item flex items-center px-3 py-2.5 rounded-lg {{ request()->routeIs('
<span x-show="sidebarOpen">Dashboard</span>
</a>
<a href="{{ route('admin.venue.index') }}"
class="nav-item flex items-center px-3 py-2.5 rounded-lg {{ request()->routeIs('admin.venue.*') ? 'active' : '' }}">
<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5 mr-2" fill="none" viewBox="0 0 24 24"
stroke="currentColor">
<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" />
</svg>
<span x-show="sidebarOpen">Kelola Venue</span>
</a>
<a href="{{ route('admin.tables.index') }}"
class="nav-item flex items-center px-3 py-2.5 rounded-lg {{ request()->routeIs('admin.tables.*') ? 'active' : '' }}">
<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5 mr-2" fill="none" viewBox="0 0 24 24"

View File

@ -21,6 +21,7 @@ class="fixed inset-0 bg-black bg-opacity-50 z-40 flex items-center justify-cente
class="w-full h-full object-cover rounded-lg mb-4 mt-8" />
<h1 class="text-xl text-gray-800 font-semibold">{{ $venue['name'] }}</h1>
<p class="text-sm text-gray-500">{{ $venue['location'] ?? 'Lokasi tidak tersedia' }}</p>
<p class="text-sm text-gray-600 mt-1">
<i class="fa-regular fa-clock"></i>
Jam Operasional: {{ date('H:i', strtotime($venue['open_time'])) }} -
@ -182,12 +183,12 @@ function showToast(message, type = 'info', duration = 5000) {
toast.className = `${bgColor} text-white px-6 py-4 rounded-lg shadow-lg flex items-center space-x-3 min-w-80 transform transition-all duration-300 translate-x-full opacity-0`;
toast.innerHTML = `
<i class="fas ${icon}"></i>
<span class="flex-1">${message}</span>
<button onclick="this.parentElement.remove()" class="text-white hover:text-gray-200">
<i class="fas fa-times"></i>
</button>
`;
<i class="fas ${icon}"></i>
<span class="flex-1">${message}</span>
<button onclick="this.parentElement.remove()" class="text-white hover:text-gray-200">
<i class="fas fa-times"></i>
</button>
`;
toastContainer.appendChild(toast);
@ -223,20 +224,20 @@ function showModal(title, message, type = 'info', callback = null) {
}[type] || 'fa-info-circle';
modal.innerHTML = `
<div class="bg-white rounded-lg p-6 max-w-md w-full shadow-2xl transform transition-all">
<div class="flex items-center space-x-3 mb-4">
<i class="fas ${icon} text-2xl ${iconColor}"></i>
<h3 class="text-lg font-semibold text-gray-800">${title}</h3>
<div class="bg-white rounded-lg p-6 max-w-md w-full shadow-2xl transform transition-all">
<div class="flex items-center space-x-3 mb-4">
<i class="fas ${icon} text-2xl ${iconColor}"></i>
<h3 class="text-lg font-semibold text-gray-800">${title}</h3>
</div>
<p class="text-gray-600 mb-6">${message}</p>
<div class="flex justify-end space-x-3">
<button onclick="this.closest('.fixed').remove(); ${callback ? callback + '()' : ''}"
class="bg-blue-500 text-white px-4 py-2 rounded-md hover:bg-blue-600 transition-colors">
OK
</button>
</div>
</div>
<p class="text-gray-600 mb-6">${message}</p>
<div class="flex justify-end space-x-3">
<button onclick="this.closest('.fixed').remove(); ${callback ? callback + '()' : ''}"
class="bg-blue-500 text-white px-4 py-2 rounded-md hover:bg-blue-600 transition-colors">
OK
</button>
</div>
</div>
`;
`;
document.body.appendChild(modal);
@ -255,22 +256,22 @@ function showConfirmModal(title, message, onConfirm, onCancel = null) {
modal.className = 'fixed inset-0 bg-black bg-opacity-50 z-50 flex items-center justify-center p-4';
modal.innerHTML = `
<div class="bg-white rounded-lg p-6 max-w-md w-full shadow-2xl transform transition-all">
<div class="flex items-center space-x-3 mb-4">
<i class="fas fa-question-circle text-2xl text-yellow-500"></i>
<h3 class="text-lg font-semibold text-gray-800">${title}</h3>
<div class="bg-white rounded-lg p-6 max-w-md w-full shadow-2xl transform transition-all">
<div class="flex items-center space-x-3 mb-4">
<i class="fas fa-question-circle text-2xl text-yellow-500"></i>
<h3 class="text-lg font-semibold text-gray-800">${title}</h3>
</div>
<p class="text-gray-600 mb-6">${message}</p>
<div class="flex justify-end space-x-3">
<button id="cancelBtn" class="bg-gray-300 text-gray-700 px-4 py-2 rounded-md hover:bg-gray-400 transition-colors">
Batal
</button>
<button id="confirmBtn" class="bg-red-500 text-white px-4 py-2 rounded-md hover:bg-red-600 transition-colors">
Ya, Hapus
</button>
</div>
</div>
<p class="text-gray-600 mb-6">${message}</p>
<div class="flex justify-end space-x-3">
<button id="cancelBtn" class="bg-gray-300 text-gray-700 px-4 py-2 rounded-md hover:bg-gray-400 transition-colors">
Batal
</button>
<button id="confirmBtn" class="bg-red-500 text-white px-4 py-2 rounded-md hover:bg-red-600 transition-colors">
Ya, Hapus
</button>
</div>
</div>
`;
`;
document.body.appendChild(modal);

View File

@ -9,6 +9,7 @@
use App\Http\Controllers\admin\TableController;
use App\Http\Controllers\admin\RevenueController;
use App\Http\Controllers\admin\AdminController;
use App\Http\Controllers\admin\VenueController as AdminVenueController; // Import admin venue controller
use App\Http\Controllers\Auth\VerificationController;
use App\Http\Controllers\superadmin\SuperAdminController;
use App\Http\Controllers\superadmin\AdminManagementController;
@ -72,6 +73,8 @@
// Admin routes (admin tetap perlu verified untuk keamanan)
Route::middleware(['auth', 'verified', 'is_admin'])->prefix('admin')->group(function () {
Route::get('/', [AdminController::class, 'index'])->name('admin.dashboard');
// Booking management routes
Route::get('/bookings', [BookingsController::class, 'index'])->name('admin.bookings.index');
Route::get('/bookings/export', [BookingsController::class, 'export'])->name('admin.bookings.export');
Route::get('/bookings/{id}', [BookingsController::class, 'show'])->name('admin.bookings.show');
@ -80,7 +83,7 @@
Route::patch('/bookings/{id}/complete', [BookingsController::class, 'complete'])->name('admin.bookings.complete');
Route::patch('/bookings/{id}/cancel', [BookingsController::class, 'cancel'])->name('admin.bookings.cancel');
// CRUD routes untuk manajemen meja
// Table management routes
Route::get('/tables', [TableController::class, 'index'])->name('admin.tables.index');
Route::get('/tables/create', [TableController::class, 'create'])->name('admin.tables.create');
Route::post('/tables', [TableController::class, 'store'])->name('admin.tables.store');
@ -88,7 +91,12 @@
Route::put('/tables/{id}', [TableController::class, 'update'])->name('admin.tables.update');
Route::delete('/tables/{id}', [TableController::class, 'destroy'])->name('admin.tables.destroy');
// CRUD routes untuk revenue
// Venue management routes
Route::get('/venue', [AdminVenueController::class, 'index'])->name('admin.venue.index');
Route::get('/venue/edit', [AdminVenueController::class, 'edit'])->name('admin.venue.edit');
Route::put('/venue/update', [AdminVenueController::class, 'update'])->name('admin.venue.update');
// Revenue management routes
Route::get('/revenues', [RevenueController::class, 'index'])->name('admin.revenues.index');
Route::get('/revenues/detail/{tableId}', [RevenueController::class, 'detail'])->name('admin.revenues.detail');
Route::get('/revenues/export', [RevenueController::class, 'export'])->name('admin.revenues.export');
@ -98,7 +106,7 @@
Route::middleware(['auth', 'verified', 'is_superadmin'])->prefix('superadmin')->group(function () {
Route::get('/', [App\Http\Controllers\superadmin\SuperAdminController::class, 'index'])->name('superadmin.dashboard');
// Tambahkan route untuk manajemen Admin
// Admin management routes
Route::get('/admin', [AdminManagementController::class, 'index'])->name('superadmin.admin.index');
Route::get('/admin/create', [AdminManagementController::class, 'create'])->name('superadmin.admin.create');
Route::post('/admin', [AdminManagementController::class, 'store'])->name('superadmin.admin.store');
@ -106,11 +114,11 @@
Route::put('/admin/{id}', [AdminManagementController::class, 'update'])->name('superadmin.admin.update');
Route::delete('/admin/{id}', [AdminManagementController::class, 'destroy'])->name('superadmin.admin.destroy');
// Tambahkan route untuk manajemen Venue
// Venue management routes (for superadmin)
Route::get('/venue', [VenueManagementController::class, 'index'])->name('superadmin.venue.index');
Route::get('/venue/create', [VenueManagementController::class, 'create'])->name('superadmin.venue.create');
Route::post('/venue', [VenueManagementController::class, 'store'])->name('superadmin.venue.store');
Route::get('/venue/{id}/edit', [VenueManagementController::class, 'edit'])->name('superadmin.venue.edit');
Route::put('/venue/{id}', [VenueManagementController::class, 'update'])->name('superadmin.venue.update');
Route::delete('/venue/{id}', [VenueManagementController::class, 'destroy'])->name('superadmin.venue.destroy');
});
});