| <x-app-layout> | |
| <x-slot name="header"> | |
| <div class="flex items-center justify-between"> | |
| <div> | |
| <h1 class="heading-1 text-white mb-2">Order Management</h1> | |
| <p class="text-blue-100">Manage all customer orders and transactions</p> | |
| </div> | |
| <div class="text-right text-white"> | |
| <div class="text-2xl font-bold">{{ $orders->count() }}</div> | |
| <div class="text-blue-100">Total Orders</div> | |
| </div> | |
| </div> | |
| </x-slot> | |
| <div class="py-8"> | |
| <div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8"> | |
| @if (session('success')) | |
| <div class="mb-6 p-4 bg-green-50 border border-green-200 rounded-lg"> | |
| <div class="flex items-center"> | |
| <i class="fas fa-check-circle text-green-600 mr-3"></i> | |
| <span class="text-green-800 font-medium">{{ session('success') }}</span> | |
| </div> | |
| </div> | |
| @endif | |
| @if (session('error')) | |
| <div class="mb-6 p-4 bg-red-50 border border-red-200 rounded-lg"> | |
| <div class="flex items-center"> | |
| <i class="fas fa-exclamation-circle text-red-600 mr-3"></i> | |
| <span class="text-red-800 font-medium">{{ session('error') }}</span> | |
| </div> | |
| </div> | |
| @endif | |
| <!-- Filter and Search Controls --> | |
| <div class="card p-6 mb-6"> | |
| <div class="flex flex-col lg:flex-row lg:items-center lg:justify-between gap-4"> | |
| <div class="flex items-center space-x-4"> | |
| <h2 class="heading-3"> | |
| <i class="fas fa-list mr-2 text-blue-600"></i>All Orders | |
| </h2> | |
| <div class="text-base text-gray-700 dark:text-gray-300 font-medium"> | |
| <span id="orderCount">{{ $orders->count() }}</span> {{ $orders->count() === 1 ? 'order' : 'orders' }} total | |
| </div> | |
| </div> | |
| <div class="flex flex-col sm:flex-row items-center space-y-3 sm:space-y-0 sm:space-x-4"> | |
| <!-- Search Box --> | |
| <div class="relative"> | |
| <input type="text" id="searchInput" placeholder="Search orders..." | |
| class="input-field pl-10 min-w-[250px]"> | |
| <div class="absolute inset-y-0 left-0 pl-3 flex items-center pointer-events-none"> | |
| <i class="fas fa-search text-gray-400"></i> | |
| </div> | |
| </div> | |
| <!-- Status Filter --> | |
| <select id="statusFilter" class="input-field min-w-[150px]"> | |
| <option value="">All Status</option> | |
| <option value="pending">PENDING</option> | |
| <option value="completed">ACCEPTED</option> | |
| <option value="cancelled">REJECTED</option> | |
| </select> | |
| <!-- Date Filter --> | |
| <select id="dateFilter" class="input-field min-w-[150px]"> | |
| <option value="">All Dates</option> | |
| <option value="today">Today</option> | |
| <option value="week">This Week</option> | |
| <option value="month">This Month</option> | |
| </select> | |
| </div> | |
| </div> | |
| </div> | |
| @if($orders->isEmpty()) | |
| <div class="text-center py-20"> | |
| <div class="max-w-md mx-auto"> | |
| <div class="w-32 h-32 bg-gradient-to-r from-purple-500/20 to-blue-500/20 rounded-full flex items-center justify-center mx-auto mb-8 border border-purple-500/30"> | |
| <i class="fas fa-shopping-bag text-5xl text-purple-400"></i> | |
| </div> | |
| <h3 class="text-3xl font-bold text-white mb-4">No Orders Yet</h3> | |
| <p class="text-white/70 mb-8 text-lg">No customer orders have been placed yet. Orders will appear here once customers start purchasing.</p> | |
| <div class="flex flex-col sm:flex-row items-center justify-center gap-4"> | |
| <a href="{{ route('categories') }}" class="btn-primary"> | |
| <i class="fas fa-store mr-2"></i>Visit Store | |
| </a> | |
| <a href="{{ route('products.listOFproduct') }}" class="btn-secondary"> | |
| <i class="fas fa-cogs mr-2"></i>Manage Products | |
| </a> | |
| </div> | |
| </div> | |
| </div> | |
| @else | |
| <!-- Orders Grid --> | |
| <div id="ordersGrid" class="space-y-4 max-w-full overflow-hidden"> | |
| @foreach ($orders as $order) | |
| @php | |
| $items = json_decode($order->cart_data, true); | |
| $orderDate = $order->created_at; | |
| @endphp | |
| <div class="order-card glass-bg p-8 border border-white/10 hover:border-purple-500/30 transition-all duration-500 group {{ $loop->last ? '' : 'mb-8' }} max-w-full overflow-hidden" | |
| data-customer="{{ strtolower($order->customer_name) }}" | |
| data-phone="{{ $order->phone }}" | |
| data-status="{{ $order->status ?? 'pending' }}" | |
| data-date="{{ $orderDate->format('Y-m-d') }}" | |
| data-date-category="{{ $orderDate->isToday() ? 'today' : ($orderDate->isCurrentWeek() ? 'week' : ($orderDate->isCurrentMonth() ? 'month' : 'older')) }}"> | |
| <div class="flex flex-col gap-10"> | |
| <!-- Enhanced Order Header --> | |
| <div class="flex items-center justify-between mb-8"> | |
| <div class="flex items-center space-x-8"> | |
| <!-- Order Icon --> | |
| <div class="w-20 h-20 bg-gradient-to-r from-purple-500 to-blue-500 rounded-2xl flex items-center justify-center shadow-lg group-hover:scale-110 transition-transform duration-300"> | |
| <i class="fas fa-receipt text-white text-2xl"></i> | |
| </div> | |
| <div> | |
| <h3 class="text-3xl font-bold text-white mb-4"> | |
| Order #{{ str_pad($order->id, 4, '0', STR_PAD_LEFT) }} | |
| </h3> | |
| <!-- Enhanced Status Badge --> | |
| <div class="flex items-center space-x-4"> | |
| <span class="px-5 py-3 rounded-xl text-sm font-semibold border {{ $order->status === 'completed' ? 'bg-green-500/20 text-green-300 border-green-500/30' : ($order->status === 'cancelled' ? 'bg-red-500/20 text-red-300 border-red-500/30' : 'bg-yellow-500/20 text-yellow-300 border-yellow-500/30') }}"> | |
| @if($order->status === 'completed') | |
| <i class="fas fa-check-circle mr-2"></i>ACCEPTED | |
| @elseif($order->status === 'cancelled') | |
| <i class="fas fa-times-circle mr-2"></i>REJECTED | |
| @else | |
| <i class="fas fa-hourglass-half mr-2"></i>PENDING | |
| @endif | |
| </span> | |
| <span class="text-white/60 text-base"> | |
| {{ $order->created_at->diffForHumans() }} | |
| </span> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- Enhanced Order Total --> | |
| <div class="text-right"> | |
| <div class="text-base text-white/60 mb-2">Total Amount</div> | |
| <div class="text-4xl font-bold text-green-400"> | |
| ฿{{ number_format($order->total_amount ?? 0, 2) }} | |
| </div> | |
| </div> | |
| </div> | |
| <!-- Enhanced Customer Info --> | |
| <div class="grid grid-cols-1 md:grid-cols-2 xl:grid-cols-4 gap-6 mb-8"> | |
| <div class="glass-bg p-4 rounded-xl border border-white/10"> | |
| <div class="flex items-center space-x-3"> | |
| <div class="w-12 h-12 bg-gradient-to-r from-blue-500 to-purple-500 rounded-lg flex items-center justify-center flex-shrink-0"> | |
| <i class="fas fa-user text-white"></i> | |
| </div> | |
| <div class="flex-1 min-w-0"> | |
| <div class="text-xs text-white/60 mb-1">Customer</div> | |
| <div class="font-semibold text-white truncate text-sm">{{ $order->customer_name }}</div> | |
| </div> | |
| </div> | |
| </div> | |
| <div class="glass-bg p-4 rounded-xl border border-white/10"> | |
| <div class="flex items-center space-x-3"> | |
| <div class="w-12 h-12 bg-gradient-to-r from-green-500 to-teal-500 rounded-lg flex items-center justify-center flex-shrink-0"> | |
| <i class="fas fa-phone text-white"></i> | |
| </div> | |
| <div class="flex-1 min-w-0"> | |
| <div class="text-xs text-white/60 mb-1">Phone</div> | |
| <div class="font-semibold text-white truncate text-sm">{{ $order->phone }}</div> | |
| </div> | |
| </div> | |
| </div> | |
| <div class="glass-bg p-4 rounded-xl border border-white/10"> | |
| <div class="flex items-center space-x-3"> | |
| <div class="w-12 h-12 bg-gradient-to-r from-purple-500 to-pink-500 rounded-lg flex items-center justify-center flex-shrink-0"> | |
| <i class="fas fa-calendar text-white"></i> | |
| </div> | |
| <div class="flex-1 min-w-0"> | |
| <div class="text-xs text-white/60 mb-1">Order Date</div> | |
| <div class="font-semibold text-white text-sm"> | |
| {{ $order->created_at->format('M j, Y') }} | |
| </div> | |
| <div class="text-xs text-white/50"> | |
| {{ $order->created_at->format('g:i A') }} | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| <div class="glass-bg p-4 rounded-xl border border-white/10"> | |
| <div class="flex items-center space-x-3"> | |
| <div class="w-12 h-12 bg-gradient-to-r from-orange-500 to-red-500 rounded-lg flex items-center justify-center flex-shrink-0"> | |
| <i class="fas fa-image text-white"></i> | |
| </div> | |
| <div class="flex-1 min-w-0"> | |
| <div class="text-xs text-white/60 mb-1">Payment Slip</div> | |
| @if ($order->payment_slip_path) | |
| <button onclick="showPaymentSlip('{{ asset('storage/' . $order->payment_slip_path) }}')" | |
| class="text-blue-400 hover:text-blue-300 font-semibold transition-colors text-sm flex items-center"> | |
| <i class="fas fa-eye mr-1"></i>View Slip | |
| </button> | |
| @else | |
| <span class="text-white/50 text-sm">No slip uploaded</span> | |
| @endif | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- Enhanced Order Items with Images --> | |
| @if (is_array($items)) | |
| <div class="border-t border-white/10 pt-6"> | |
| <h4 class="text-xl font-semibold text-white mb-6 flex items-center"> | |
| <i class="fas fa-shopping-cart mr-3 text-purple-400"></i>Order Items | |
| <span class="ml-3 px-3 py-2 bg-purple-500/20 text-purple-300 text-sm rounded-full"> | |
| {{ count($items) }} {{ count($items) === 1 ? 'item' : 'items' }} | |
| </span> | |
| </h4> | |
| <div class="space-y-6"> | |
| @foreach ($items as $item) | |
| @php | |
| // Get product details from database | |
| $product = \App\Models\Product::find($item['id'] ?? null); | |
| @endphp | |
| <div class="glass-bg p-6 rounded-xl border border-white/10 hover:border-purple-500/30 transition-all duration-300"> | |
| <div class="flex items-center space-x-6"> | |
| <!-- Product Image --> | |
| <div class="flex-shrink-0"> | |
| @if($product && $product->image) | |
| <img src="{{ $product->image }}" | |
| alt="{{ $item['name'] }}" | |
| class="w-16 h-16 object-cover rounded-lg border border-white/20 shadow-lg"> | |
| @else | |
| <div class="w-16 h-16 bg-gradient-to-r from-purple-500 to-blue-500 rounded-lg flex items-center justify-center"> | |
| <i class="fas fa-gamepad text-white text-xl"></i> | |
| </div> | |
| @endif | |
| </div> | |
| <!-- Product Details --> | |
| <div class="flex-1 min-w-0"> | |
| <div class="flex items-start justify-between"> | |
| <div class="flex-1"> | |
| <h5 class="text-white font-semibold text-base mb-1 truncate"> | |
| {{ $item['name'] }} | |
| </h5> | |
| <!-- Game Category Badge --> | |
| @if($product && $product->game) | |
| <div class="mb-4"> | |
| <span class="px-3 py-2 rounded-full text-sm font-medium @switch($product->game) @case('Genshin') bg-yellow-500/20 text-yellow-300 border border-yellow-500/30 @break @case('Starrail') bg-purple-500/20 text-purple-300 border border-purple-500/30 @break @case('WutheringWave') bg-cyan-500/20 text-cyan-300 border border-cyan-500/30 @break @default bg-blue-500/20 text-blue-300 border border-blue-500/30 @endswitch"> | |
| @switch($product->game) | |
| @case('Genshin') | |
| <i class="fas fa-star mr-2"></i>Genshin Impact | |
| @break | |
| @case('Starrail') | |
| <i class="fas fa-rocket mr-2"></i>Honkai: Star Rail | |
| @break | |
| @case('WutheringWave') | |
| <i class="fas fa-wave-square mr-2"></i>Wuthering Waves | |
| @break | |
| @default | |
| <i class="fas fa-gamepad mr-2"></i>{{ $product->game }} | |
| @endswitch | |
| </span> | |
| </div> | |
| @endif | |
| <!-- Quantity and Price --> | |
| <div class="flex items-center space-x-6 text-base"> | |
| <span class="flex items-center text-white/70"> | |
| <i class="fas fa-hashtag mr-2 text-blue-400"></i> | |
| Qty: <span class="font-semibold ml-2">{{ $item['quantity'] }}</span> | |
| </span> | |
| <span class="flex items-center text-white/70"> | |
| <i class="fas fa-tag mr-2 text-green-400"></i> | |
| ฿{{ number_format($item['price'] ?? 0, 2) }} each | |
| </span> | |
| </div> | |
| </div> | |
| <!-- Item Total --> | |
| <div class="text-right ml-6"> | |
| <div class="text-2xl font-bold text-green-400"> | |
| ฿{{ number_format(($item['price'] ?? 0) * ($item['quantity'] ?? 1), 2) }} | |
| </div> | |
| <div class="text-sm text-white/50 mt-1">Total</div> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| @endforeach | |
| </div> | |
| <!-- Order Summary --> | |
| <div class="mt-6 p-4 bg-gradient-to-r from-purple-500/10 to-blue-500/10 rounded-xl border border-purple-500/20"> | |
| <div class="flex items-center justify-between"> | |
| <div class="flex items-center space-x-2"> | |
| <i class="fas fa-calculator text-purple-400"></i> | |
| <span class="text-white font-medium">Order Total</span> | |
| </div> | |
| <div class="text-2xl font-bold text-purple-400"> | |
| ฿{{ number_format($order->total_amount ?? 0, 2) }} | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| @endif | |
| </div> | |
| <!-- Enhanced Actions --> | |
| <div class="flex items-center justify-between pt-8 border-t border-white/10 mt-8"> | |
| <div class="flex items-center space-x-4"> | |
| <div class="text-base text-white/60"> | |
| <i class="fas fa-info-circle mr-2"></i> | |
| Order created {{ $order->created_at->diffForHumans() }} | |
| </div> | |
| </div> | |
| <div class="flex items-center space-x-4"> | |
| <a href="{{ route('orders.show', $order->id) }}" class="btn-secondary px-6 py-3"> | |
| <i class="fas fa-eye mr-2"></i>View Details | |
| </a> | |
| @if($order->status === 'pending') | |
| <form action="{{ route('orders.complete', $order->id) }}" method="POST" class="inline-block"> | |
| @csrf | |
| @method('PATCH') | |
| <button type="submit" class="px-6 py-3 bg-gradient-to-r from-green-600 to-emerald-600 hover:from-green-500 hover:to-emerald-500 text-white rounded-xl font-bold transition-all duration-300 shadow-lg hover:shadow-green-500/40 transform hover:scale-105"> | |
| <i class="fas fa-check-circle mr-2"></i>ACCEPT | |
| </button> | |
| </form> | |
| <form action="{{ route('orders.reject', $order->id) }}" method="POST" | |
| class="inline-block" | |
| onsubmit="return confirm('Are you sure you want to reject this order? The customer will see it as cancelled.');"> | |
| @csrf | |
| @method('PATCH') | |
| <button type="submit" class="px-6 py-3 bg-gradient-to-r from-red-600 to-rose-600 hover:from-red-500 hover:to-rose-500 text-white rounded-xl font-bold transition-all duration-300 shadow-lg hover:shadow-red-500/40 transform hover:scale-105"> | |
| <i class="fas fa-times-circle mr-2"></i>REJECT | |
| </button> | |
| </form> | |
| @elseif($order->status === 'completed') | |
| <span class="px-6 py-3 bg-green-500/20 text-green-300 rounded-xl font-bold border border-green-500/30"> | |
| <i class="fas fa-check-circle mr-2"></i>ACCEPTED | |
| </span> | |
| @elseif($order->status === 'cancelled') | |
| <span class="px-6 py-3 bg-red-500/20 text-red-300 rounded-xl font-bold border border-red-500/30"> | |
| <i class="fas fa-times-circle mr-2"></i>REJECTED | |
| </span> | |
| @endif | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| @endforeach | |
| </div> | |
| <!-- No Results Message --> | |
| <div id="noResults" class="hidden text-center py-12"> | |
| <div class="w-16 h-16 bg-gray-100 dark:bg-gray-800 rounded-full flex items-center justify-center mx-auto mb-4"> | |
| <i class="fas fa-search text-gray-400 text-2xl"></i> | |
| </div> | |
| <h3 class="text-lg font-semibold text-gray-900 dark:text-white mb-2">No orders found</h3> | |
| <p class="text-gray-600 dark:text-gray-400">Try adjusting your search or filter criteria.</p> | |
| </div> | |
| @endif | |
| </div> | |
| </div> | |
| <!-- Payment Slip Modal --> | |
| <div id="paymentSlipModal" class="fixed inset-0 bg-black/50 backdrop-blur-sm hidden items-center justify-center z-50 p-4"> | |
| <div class="bg-black/30 backdrop-filter backdrop-blur-20 border border-white/10 rounded-2xl max-w-4xl w-full max-h-[90vh] flex flex-col"> | |
| <div class="flex-shrink-0 flex items-center justify-between p-6 border-b border-white/10"> | |
| <h3 class="text-xl font-semibold text-white">Payment Slip</h3> | |
| <button onclick="closePaymentSlip()" class="text-white/60 hover:text-white text-2xl transition-colors"> | |
| <i class="fas fa-times"></i> | |
| </button> | |
| </div> | |
| <div class="flex-1 overflow-hidden p-6"> | |
| <div class="flex items-center justify-center h-full"> | |
| <img id="paymentSlipImage" src="" alt="Payment slip" | |
| class="max-w-full max-h-full object-contain rounded-lg shadow-lg"> | |
| </div> | |
| </div> | |
| <div class="flex-shrink-0 p-6 border-t border-white/10"> | |
| <div class="flex justify-center space-x-4"> | |
| <button onclick="downloadPaymentSlip()" class="btn-secondary"> | |
| <i class="fas fa-download mr-2"></i>Download | |
| </button> | |
| <button onclick="closePaymentSlip()" class="btn-primary"> | |
| Close | |
| </button> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| </x-app-layout> | |
| <script> | |
| // Filtering functionality | |
| const searchInput = document.getElementById('searchInput'); | |
| const statusFilter = document.getElementById('statusFilter'); | |
| const dateFilter = document.getElementById('dateFilter'); | |
| const orderCards = document.querySelectorAll('.order-card'); | |
| const noResults = document.getElementById('noResults'); | |
| const orderCount = document.getElementById('orderCount'); | |
| function filterOrders() { | |
| const searchTerm = searchInput.value.toLowerCase(); | |
| const selectedStatus = statusFilter.value; | |
| const selectedDate = dateFilter.value; | |
| let visibleCount = 0; | |
| orderCards.forEach(card => { | |
| const customer = card.dataset.customer; | |
| const phone = card.dataset.phone; | |
| const status = card.dataset.status; | |
| const dateCategory = card.dataset.dateCategory; | |
| // Check search term | |
| const matchesSearch = searchTerm === '' || | |
| customer.includes(searchTerm) || | |
| phone.includes(searchTerm); | |
| // Check status filter | |
| const matchesStatus = selectedStatus === '' || status === selectedStatus; | |
| // Check date filter | |
| const matchesDate = selectedDate === '' || dateCategory === selectedDate; | |
| if (matchesSearch && matchesStatus && matchesDate) { | |
| card.style.display = 'block'; | |
| visibleCount++; | |
| } else { | |
| card.style.display = 'none'; | |
| } | |
| }); | |
| // Update order count | |
| orderCount.textContent = visibleCount; | |
| // Show/hide no results message | |
| if (visibleCount === 0 && orderCards.length > 0) { | |
| noResults.classList.remove('hidden'); | |
| } else { | |
| noResults.classList.add('hidden'); | |
| } | |
| } | |
| // Add event listeners for filtering | |
| searchInput.addEventListener('input', filterOrders); | |
| statusFilter.addEventListener('change', filterOrders); | |
| dateFilter.addEventListener('change', filterOrders); | |
| // Enhanced delete confirmation | |
| document.querySelectorAll('form[method="POST"]').forEach(form => { | |
| form.addEventListener('submit', function(e) { | |
| const button = this.querySelector('button[type="submit"]'); | |
| if (button && button.innerHTML.includes('Delete')) { | |
| const originalText = button.innerHTML; | |
| button.innerHTML = '<i class="fas fa-spinner fa-spin mr-2"></i>Deleting...'; | |
| button.disabled = true; | |
| // Reset if there's an error (form doesn't submit) | |
| setTimeout(() => { | |
| if (button.disabled) { | |
| button.innerHTML = originalText; | |
| button.disabled = false; | |
| } | |
| }, 5000); | |
| } | |
| }); | |
| }); | |
| // Payment slip modal functions | |
| function showPaymentSlip(imageSrc) { | |
| const modal = document.getElementById('paymentSlipModal'); | |
| const image = document.getElementById('paymentSlipImage'); | |
| image.src = imageSrc; | |
| modal.classList.remove('hidden'); | |
| modal.classList.add('flex'); | |
| // Prevent body scroll | |
| document.body.style.overflow = 'hidden'; | |
| } | |
| function closePaymentSlip() { | |
| const modal = document.getElementById('paymentSlipModal'); | |
| const image = document.getElementById('paymentSlipImage'); | |
| modal.classList.add('hidden'); | |
| modal.classList.remove('flex'); | |
| image.src = ''; | |
| // Restore body scroll | |
| document.body.style.overflow = 'auto'; | |
| } | |
| function downloadPaymentSlip() { | |
| const image = document.getElementById('paymentSlipImage'); | |
| const link = document.createElement('a'); | |
| link.href = image.src; | |
| link.download = 'payment-slip.jpg'; | |
| document.body.appendChild(link); | |
| link.click(); | |
| document.body.removeChild(link); | |
| } | |
| // Close modal when clicking outside | |
| document.getElementById('paymentSlipModal').addEventListener('click', function(e) { | |
| if (e.target === e.currentTarget) { | |
| closePaymentSlip(); | |
| } | |
| }); | |
| // Close modal with Escape key | |
| document.addEventListener('keydown', function(e) { | |
| if (e.key === 'Escape') { | |
| closePaymentSlip(); | |
| } | |
| }); | |
| // Add smooth animations | |
| document.addEventListener('DOMContentLoaded', function() { | |
| // Animate cards on load | |
| const cards = document.querySelectorAll('.order-card'); | |
| cards.forEach((card, index) => { | |
| card.style.opacity = '0'; | |
| card.style.transform = 'translateY(20px)'; | |
| setTimeout(() => { | |
| card.style.transition = 'all 0.5s ease'; | |
| card.style.opacity = '1'; | |
| card.style.transform = 'translateY(0)'; | |
| }, index * 100); | |
| }); | |
| }); | |
| </script> | |
| <style> | |
| /* Enhanced Order Card Styling */ | |
| .order-card { | |
| transition: all 0.4s cubic-bezier(0.4, 0, 0.2, 1); | |
| position: relative; | |
| overflow: hidden; | |
| width: 100%; | |
| max-width: 100%; | |
| box-sizing: border-box; | |
| } | |
| /* Ensure all child elements respect container width */ | |
| .order-card * { | |
| max-width: 100%; | |
| box-sizing: border-box; | |
| } | |
| .order-card::before { | |
| content: ''; | |
| position: absolute; | |
| top: 0; | |
| left: -100%; | |
| width: 100%; | |
| height: 100%; | |
| background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.05), transparent); | |
| transition: left 0.6s ease; | |
| } | |
| .order-card:hover::before { | |
| left: 100%; | |
| } | |
| .order-card:hover { | |
| transform: translateY(-8px) scale(1.02); | |
| box-shadow: | |
| 0 25px 50px rgba(0, 0, 0, 0.4), | |
| 0 0 50px rgba(139, 92, 246, 0.2); | |
| border-color: rgba(139, 92, 246, 0.5); | |
| } | |
| /* Product Image Hover Effects */ | |
| .order-card img { | |
| transition: all 0.3s ease; | |
| } | |
| .order-card:hover img { | |
| transform: scale(1.1); | |
| box-shadow: 0 8px 25px rgba(139, 92, 246, 0.3); | |
| } | |
| /* Enhanced Glass Effect for Item Cards */ | |
| .glass-bg { | |
| backdrop-filter: blur(20px); | |
| background: rgba(0, 0, 0, 0.3); | |
| transition: all 0.3s ease; | |
| } | |
| .glass-bg:hover { | |
| background: rgba(0, 0, 0, 0.4); | |
| transform: translateY(-2px); | |
| } | |
| /* Gradient Text Animation */ | |
| .bg-clip-text { | |
| background-clip: text; | |
| -webkit-background-clip: text; | |
| -webkit-text-fill-color: transparent; | |
| } | |
| /* Enhanced Payment Slip Modal */ | |
| #paymentSlipModal { | |
| backdrop-filter: blur(20px); | |
| } | |
| #paymentSlipModal img { | |
| transition: transform 0.3s ease; | |
| max-height: 70vh; | |
| } | |
| #paymentSlipModal img:hover { | |
| transform: scale(1.05); | |
| } | |
| /* Loading Animation for Delete Button */ | |
| .btn-danger:disabled { | |
| opacity: 0.6; | |
| cursor: not-allowed; | |
| } | |
| /* Smooth Fade In Animation */ | |
| @keyframes fadeInUp { | |
| from { | |
| opacity: 0; | |
| transform: translateY(30px); | |
| } | |
| to { | |
| opacity: 1; | |
| transform: translateY(0); | |
| } | |
| } | |
| .order-card { | |
| animation: fadeInUp 0.6s ease-out; | |
| } | |
| /* Stagger Animation Delays */ | |
| .order-card:nth-child(1) { animation-delay: 0.1s; } | |
| .order-card:nth-child(2) { animation-delay: 0.2s; } | |
| .order-card:nth-child(3) { animation-delay: 0.3s; } | |
| .order-card:nth-child(4) { animation-delay: 0.4s; } | |
| .order-card:nth-child(5) { animation-delay: 0.5s; } | |
| /* Custom Scrollbar */ | |
| .order-card::-webkit-scrollbar { | |
| width: 8px; | |
| } | |
| .order-card::-webkit-scrollbar-track { | |
| background: rgba(255, 255, 255, 0.1); | |
| border-radius: 4px; | |
| } | |
| .order-card::-webkit-scrollbar-thumb { | |
| background: rgba(139, 92, 246, 0.6); | |
| border-radius: 4px; | |
| } | |
| .order-card::-webkit-scrollbar-thumb:hover { | |
| background: rgba(139, 92, 246, 0.8); | |
| } | |
| /* Orders Grid Container */ | |
| #ordersGrid { | |
| width: 100%; | |
| max-width: 100%; | |
| overflow-x: hidden; | |
| contain: layout; | |
| } | |
| /* Force order cards to respect container bounds */ | |
| .order-card { | |
| contain: layout; | |
| min-width: 0; | |
| } | |
| /* Ensure grid items don't overflow */ | |
| .order-card .grid { | |
| min-width: 0; | |
| } | |
| .order-card .grid > * { | |
| min-width: 0; | |
| max-width: 100%; | |
| } | |
| /* Ensure proper responsive behavior */ | |
| @media (max-width: 768px) { | |
| .order-card { | |
| margin-left: 0; | |
| margin-right: 0; | |
| } | |
| .order-card .grid { | |
| grid-template-columns: 1fr; | |
| } | |
| } | |
| @media (max-width: 1280px) { | |
| .order-card .grid.xl\\:grid-cols-4 { | |
| grid-template-columns: repeat(2, minmax(0, 1fr)); | |
| } | |
| } | |
| </style> |