Kelola Venue by Admin bisa, tapi bookingnya error lg
This commit is contained in:
parent
0580940cf5
commit
64951d2018
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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()
|
||||
{
|
||||
|
|
|
@ -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
|
|
@ -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
|
|
@ -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"
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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');
|
||||
});
|
||||
});
|
Loading…
Reference in New Issue