312 lines
18 KiB
PHP
312 lines
18 KiB
PHP
<div class="flex h-screen bg-gray-100 font-sans">
|
|
{{-- Kiri: Sidemenu Kategori --}}
|
|
<div class="w-64 bg-white shadow-lg overflow-y-auto p-4 z-20">
|
|
<h1 class="text-5xl font-bold mb-6 text-center text-gray-800">DFOOD</h1>
|
|
<nav>
|
|
<ul class="space-y-4">
|
|
@foreach ($allTypeItems as $type)
|
|
<li class="mb-2">
|
|
<a href="#" wire:click.prevent="filterByType({{ $type->id }})"
|
|
class="block rounded overflow-hidden shadow-md transition-all duration-200
|
|
{{ $typeItemId == $type->id ? 'ring-2 ring-green-600 ring-offset-2' : 'hover:scale-105' }}">
|
|
@php
|
|
$imageUrl = $type->image_url;
|
|
if (!filter_var($imageUrl, FILTER_VALIDATE_URL)) {
|
|
$imageUrl = asset($imageUrl);
|
|
}
|
|
@endphp
|
|
<img src="{{ $imageUrl }}" class="w-full h-32 object-cover" alt="{{ $type->name }}"
|
|
loading="lazy" decoding="async">
|
|
<div
|
|
class="text-center py-3 border-t border-gray-200 text-gray-800 font-medium
|
|
{{ $typeItemId == $type->id ? 'bg-green-600 text-white' : 'bg-gray-50' }}">
|
|
{{ $type->name }}
|
|
</div>
|
|
</a>
|
|
</li>
|
|
@endforeach
|
|
</ul>
|
|
</nav>
|
|
</div>
|
|
{{-- Tengah: Konten Utama (Daftar Makanan) --}}
|
|
<div class="flex-1 overflow-y-auto p-6">
|
|
<div class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 gap-6">
|
|
@forelse ($foodItems as $item)
|
|
<div wire:click="addToCart({{ $item->id }})"
|
|
class="bg-white cursor-pointer shadow rounded-lg overflow-hidden
|
|
transition transform hover:scale-105 active:scale-95
|
|
active:ring-2 active:ring-green-400 flex flex-col">
|
|
@if (isset($item->image_url) && $item->image_url)
|
|
<img src="{{ asset($item->image_url) }}" alt="{{ $item->name }}"
|
|
class="w-full h-48 object-cover object-center" loading="lazy" decoding="async" />
|
|
@else
|
|
<img src="{{ asset('img/placeholder-food.jpg') }}" alt="{{ $item->name }}"
|
|
class="w-full h-48 object-cover object-center" loading="lazy" decoding="async" />
|
|
@endif
|
|
|
|
<div class="p-4 flex flex-col flex-grow">
|
|
<h2 class="text-xl font-semibold leading-tight text-gray-800 mb-2">{{ $item->name }}</h2>
|
|
<p class="text-gray-600 text-lg">Rp {{ number_format($item->price, 0, ',', '.') }}</p>
|
|
</div>
|
|
</div>
|
|
@empty
|
|
<div class="col-span-full text-center py-10 bg-white rounded-lg shadow">
|
|
<p class="text-gray-500 text-xl">Tidak ada menu tersedia untuk kategori ini.</p>
|
|
</div>
|
|
@endforelse
|
|
</div>
|
|
</div>
|
|
|
|
{{-- Kanan: Sidebar Keranjang & Pembayaran --}}
|
|
<div
|
|
class="fixed top-0 right-0 h-full w-96 bg-white shadow-xl z-30 flex flex-col transform
|
|
transition-transform duration-300 ease-in-out
|
|
{{ $showCart ? 'translate-x-0' : 'translate-x-full' }}">
|
|
<div class="p-6 border-b border-gray-200 flex justify-between items-center">
|
|
<h2 id="cart-title" class="text-2xl font-bold text-gray-800">Keranjang Anda</h2>
|
|
<button wire:click="closeCart" class="text-gray-500 hover:text-gray-700 focus:outline-none"
|
|
aria-label="Close cart" type="button">
|
|
<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="M6 18L18 6M6 6l12 12" />
|
|
</svg>
|
|
</button>
|
|
</div>
|
|
|
|
<div class="flex-1 overflow-y-auto p-6">
|
|
@if (empty($cartItems))
|
|
<p class="text-gray-500 text-center py-10">Keranjang kosong.</p>
|
|
@else
|
|
{{-- Di dalam modal keranjang, di bagian 'Pilih Meja Anda' --}}
|
|
<div class="p-4 bg-white rounded-lg shadow-md mb-6">
|
|
<h3 class="text-xl font-semibold mb-4 text-gray-800">Pilih Meja Anda</h3>
|
|
|
|
{{-- Checkbox untuk memilih jenis pemesanan meja --}}
|
|
<div class="mb-4 flex items-center">
|
|
<input type="checkbox" id="is-existing-customer" wire:model.live="isExistingCustomer"
|
|
class="mr-2 form-checkbox h-5 w-5 text-blue-600">
|
|
<label for="is-existing-customer" class="text-gray-700 text-sm font-bold">Saya sudah memesan
|
|
meja.</label>
|
|
</div>
|
|
|
|
{{-- Kondisional untuk menampilkan dropdown meja tersedia atau meja terisi --}}
|
|
@if (!$isExistingCustomer)
|
|
{{-- Dropdown untuk Meja Tersedia --}}
|
|
<div class="mb-4">
|
|
<label for="available-table-select" class="block text-gray-700 text-sm font-bold mb-2">Meja
|
|
Tersedia:</label>
|
|
<select id="available-table-select" wire:model.live="selectedTableId"
|
|
class="shadow appearance-none border rounded w-full py-2 px-3 text-gray-700 leading-tight focus:outline-none focus:shadow-outline"
|
|
{{ $tableIdFromUrl && $selectedOccupiedTableId === null ? 'disabled' : '' }}>
|
|
<option value="">-- Pilih Meja Tersedia --</option>
|
|
@foreach ($availableTables as $table)
|
|
<option value="{{ $table['id'] }}">
|
|
{{ $table['device_id'] }} || TERSEDIA
|
|
</option>
|
|
@endforeach
|
|
</select>
|
|
@error('selectedTableId')
|
|
<span class="text-red-500 text-sm mt-1">{{ $message }}</span>
|
|
@enderror
|
|
</div>
|
|
@else
|
|
{{-- Dropdown untuk Meja Sudah Terisi (dengan Nama Pemesan) --}}
|
|
@if (!empty($occupiedTables))
|
|
<div class="mb-4">
|
|
<label for="occupied-table-select"
|
|
class="block text-gray-700 text-sm font-bold mb-2">Meja Sudah Terisi (Konfirmasi
|
|
Nama):</label>
|
|
<select id="occupied-table-select" wire:model.live="selectedOccupiedTableId"
|
|
class="shadow appearance-none border rounded w-full py-2 px-3 text-gray-700 leading-tight focus:outline-none focus:shadow-outline"
|
|
{{ $tableIdFromUrl && $selectedTableId === null ? 'disabled' : '' }}>
|
|
<option value="">-- Pilih Meja Terisi --</option>
|
|
@foreach ($occupiedTables as $table)
|
|
<option value="{{ $table['id'] }}">
|
|
{{ $table['device_id'] }} || Oleh: {{ $table['reserved_by'] }}
|
|
</option>
|
|
@endforeach
|
|
</select>
|
|
@error('selectedOccupiedTableId')
|
|
<span class="text-red-500 text-sm mt-1">{{ $message }}</span>
|
|
@enderror
|
|
</div>
|
|
@else
|
|
<p class="text-gray-600 text-sm">Tidak ada meja yang saat ini terisi dengan nama pemesan.
|
|
</p>
|
|
@endif
|
|
@endif
|
|
|
|
{{-- Input Nama Pemesan (TERBARU: Hanya muncul jika showCustomerNameInput TRUE) --}}
|
|
@if ($showCustomerNameInput)
|
|
<div class="mb-4">
|
|
<label for="customer-name-input" class="block text-gray-700 text-sm font-bold mb-2">Nama
|
|
Pemesan:</label>
|
|
<input type="text" id="customer-name-input" wire:model.live="inputCustomerName"
|
|
class="shadow appearance-none border rounded w-full py-2 px-3 text-gray-700 leading-tight focus:outline-none focus:shadow-outline"
|
|
placeholder="Masukkan nama Anda" {{ $isCustomerNameInputDisabled ? 'disabled' : '' }}>
|
|
@error('inputCustomerName')
|
|
<span class="text-red-500 text-sm mt-1">{{ $message }}</span>
|
|
@enderror
|
|
</div>
|
|
@endif
|
|
|
|
{{-- Tombol Lihat Denah Meja --}}
|
|
<div class="mb-4">
|
|
<button wire:click="showMap"
|
|
class="w-full bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded focus:outline-none focus:shadow-outline">
|
|
Lihat Denah Meja
|
|
</button>
|
|
</div>
|
|
</div>
|
|
|
|
{{-- Daftar Item Keranjang --}}
|
|
<ul class="divide-y divide-gray-200 mb-4" tabindex="0">
|
|
@foreach ($cartItems as $item)
|
|
<li class="py-3 flex justify-between items-center">
|
|
<div>
|
|
<p class="font-medium text-gray-800">{{ $item['name'] }}</p>
|
|
<p class="text-sm text-gray-600">Rp
|
|
{{ number_format($item['price'], 0, ',', '.') }}</p>
|
|
</div>
|
|
<div class="flex items-center gap-2">
|
|
<button wire:click="removeFromCart({{ $item['id'] }})" type="button"
|
|
class="px-2 py-1 bg-red-100 text-red-700 rounded hover:bg-red-200">
|
|
-
|
|
</button>
|
|
<span class="mx-1 text-gray-800 font-semibold">{{ $item['qty'] }}</span>
|
|
<button wire:click="addToCart({{ $item['id'] }})" type="button"
|
|
class="px-2 py-1 bg-green-100 text-green-700 rounded hover:bg-green-200">
|
|
+
|
|
</button>
|
|
</div>
|
|
</li>
|
|
@endforeach
|
|
</ul>
|
|
@endif
|
|
</div>
|
|
|
|
{{-- Footer Keranjang (Total dan Tombol Pembayaran) --}}
|
|
<div class="p-6 border-t border-gray-200 bg-white">
|
|
<div class="mb-4 text-right text-xl text-gray-900">Total: Rp
|
|
{{ number_format($cartTotal, 0, ',', '.') }}</div>
|
|
|
|
{{-- Input Email (jika showEmailInput true) --}}
|
|
@if ($showEmailInput)
|
|
<div class="mt-4 mb-4">
|
|
<label for="customerEmail" class="block text-gray-700 text-sm font-bold mb-2">Email Anda:</label>
|
|
<input type="email" id="customerEmail" wire:model.defer="customerEmail"
|
|
class="shadow appearance-none border rounded w-full py-2 px-3 text-gray-700 leading-tight focus:outline-none focus:shadow-outline"
|
|
placeholder="nama@contoh.com">
|
|
@error('customerEmail')
|
|
<span class="text-red-500 text-sm mt-1">{{ $message }}</span>
|
|
@enderror
|
|
</div>
|
|
@endif
|
|
|
|
{{-- Tombol Pembayaran --}}
|
|
<div class="flex flex-col space-y-3 mt-4">
|
|
<button wire:click="checkout"
|
|
class="bg-green-600 hover:bg-green-700 text-white py-2 rounded focus:outline-none focus:ring-2 focus:ring-green-500 font-semibold text-lg"
|
|
type="button" wire:loading.attr="disabled" wire:loading.class="opacity-50">
|
|
<span wire:loading.remove wire:target="checkout">Bayar Sekarang (Midtrans)</span>
|
|
<span wire:loading wire:target="checkout">Processing...</span>
|
|
</button>
|
|
|
|
{{-- Menggunakan $showEmailInput untuk toggle form, bukan tombol terpisah --}}
|
|
@if (!$showEmailInput && empty(auth()->user()->email))
|
|
<button wire:click="$toggle('showEmailInput')"
|
|
class="bg-blue-600 hover:bg-blue-700 text-white py-2 rounded focus:outline-none focus:ring-2 focus:ring-blue-500 font-semibold text-lg"
|
|
type="button" wire:loading.attr="disabled" wire:loading.class="opacity-50">
|
|
<span wire:loading.remove wire:target="$toggle('showEmailInput')">Bayar Nanti (Kirim Email
|
|
Receipt)</span>
|
|
<span wire:loading wire:target="$toggle('showEmailInput')">Processing...</span>
|
|
</button>
|
|
@elseif($showEmailInput)
|
|
<button wire:click="sendReceiptEmail"
|
|
class="bg-indigo-500 hover:bg-indigo-600 text-white font-bold py-2 px-4 rounded-lg"
|
|
type="button" wire:loading.attr="disabled" wire:loading.class="opacity-50">
|
|
<span wire:loading.remove wire:target="sendReceiptEmail">Kirim Email & Pesan</span>
|
|
<span wire:loading wire:target="sendReceiptEmail">Mengirim...</span>
|
|
</button>
|
|
<button wire:click="$toggle('showEmailInput')"
|
|
class="bg-gray-300 hover:bg-gray-400 text-gray-800 font-bold py-2 px-4 rounded-lg"
|
|
type="button">
|
|
Batal
|
|
</button>
|
|
@endif
|
|
|
|
|
|
<button wire:click="skipPayment"
|
|
class="bg-gray-600 hover:bg-gray-700 text-white py-2 rounded focus:outline-none focus:ring-2 focus:ring-gray-500 font-semibold text-lg"
|
|
type="button" wire:loading.attr="disabled" wire:loading.class="opacity-50">
|
|
<span wire:loading.remove wire:target="skipPayment">Lewati Pembayaran</span>
|
|
<span wire:loading wire:target="skipPayment">Processing...</span>
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
{{-- Overlay untuk sidebar keranjang --}}
|
|
@if ($showCart)
|
|
<div class="fixed inset-0 bg-black bg-opacity-50 z-20" wire:click="closeCart">
|
|
{{-- Ini adalah div overlay --}}
|
|
<div class="absolute inset-0 blur-background"></div> {{-- Div blur palsu --}}
|
|
</div>
|
|
@endif
|
|
|
|
{{-- Tombol Keranjang Mengambang --}}
|
|
<div class="fixed bottom-4 right-4 z-10"> {{-- Z-index diatur lebih rendah dari sidebar dan modal --}}
|
|
<button wire:click="openCart"
|
|
class="bg-green-600 text-white rounded-full py-3 px-6 shadow-lg hover:bg-green-700 transition flex items-center gap-3">
|
|
<svg xmlns="http://www.w3.org/2000/svg" class="h-7 w-7" fill="none" viewBox="0 0 24 24"
|
|
stroke="currentColor">
|
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
|
|
d="M3 3h2l.4 2M7 13h10l4-8H5.4M7 13L5.4 5M7 13l-2.293 2.293c-.63.63-.184 1.707.707 1.707H17m0 0a2 2 0 100 4 2 2 0 000-4zm-8 2a2 2 0 11-4 0 2 2 0 014 0z" />
|
|
</svg>
|
|
<span class="font-semibold text-xl">Keranjang ({{ array_sum($cart) }})</span>
|
|
</button>
|
|
</div>
|
|
|
|
{{-- Modal Denah Meja --}}
|
|
@if ($showMapModal)
|
|
<div class="fixed inset-0 bg-black bg-opacity-75 z-[60] flex items-center justify-center" role="dialog"
|
|
aria-modal="true" aria-labelledby="map-title">
|
|
<div class="bg-white w-full max-w-2xl lg:max-w-4xl xl:max-w-5xl rounded shadow-lg p-6 relative">
|
|
<h2 id="map-title" class="text-xl font-bold mb-4">Denah Meja Cafe</h2>
|
|
|
|
<div class="relative w-full overflow-hidden border border-gray-300 rounded-lg"
|
|
style="max-height: 80vh;">
|
|
<img src="{{ asset('img/denah_cafe.jpg') }}" alt="Denah Cafe"
|
|
class="w-full h-auto object-contain">
|
|
</div>
|
|
|
|
<div class="mt-6 text-right">
|
|
<button wire:click="closeMap" type="button"
|
|
class="bg-gray-300 hover:bg-gray-400 text-gray-800 font-bold py-2 px-4 rounded-lg">
|
|
Tutup
|
|
</button>
|
|
</div>
|
|
|
|
<button wire:click="closeMap"
|
|
class="absolute top-2 right-2 text-gray-500 hover:text-gray-700 focus:outline-none"
|
|
aria-label="Close map" type="button">
|
|
✕
|
|
</button>
|
|
</div>
|
|
</div>
|
|
@endif
|
|
|
|
<div x-data="{ notification: false, message: '' }"
|
|
x-on:notify.window="notification = true; message = $event.detail.message; setTimeout(() => notification = false, 3000)"
|
|
x-cloak>
|
|
<div x-show="notification" x-transition:enter="transition ease-out duration-300"
|
|
x-transition:enter-start="opacity-0 transform translate-y-2"
|
|
x-transition:enter-end="opacity-100 transform translate-y-0"
|
|
x-transition:leave="transition ease-in duration-200"
|
|
x-transition:leave-start="opacity-100 transform translate-y-0"
|
|
x-transition:leave-end="opacity-0 transform translate-y-2"
|
|
class="fixed bottom-8 left-1/2 -translate-x-1/2 bg-green-500 text-white px-4 py-2 rounded-lg shadow-lg z-50">
|
|
<p x-text="message"></p>
|
|
</div>
|
|
</div>
|
|
</div>
|