gamtest / resources /views /table_product.blade.php
veela4's picture
Upload folder using huggingface_hub
70ba896 verified
<x-app-layout>
<x-slot name="header">
<div class="flex items-center justify-between">
<div>
<h1 class="heading-2 mb-2">Product Management</h1>
<p class="text-muted">Manage your store inventory with precision and ease</p>
</div>
<button id="show_category_modal" class="btn-primary">
<i class="fas fa-plus mr-2"></i>Add New Product
</button>
</div>
</x-slot>
<div class="py-12">
<div class="container-custom">
@if (session('success'))
<div class="card mb-6 bg-green-900/30 border-green-500/30">
<div class="flex items-center">
<i class="fas fa-check-circle text-green-400 mr-3 text-xl"></i>
<span class="text-green-300 font-medium">{{ session('success') }}</span>
</div>
</div>
@endif
<!-- Product Inventory Card -->
<div class="card mb-8">
<!-- Header Section -->
<div class="flex flex-col lg:flex-row lg:items-center justify-between mb-8 gap-6">
<div class="flex items-center">
<div class="w-12 h-12 bg-gradient-to-r from-blue-500 to-purple-500 rounded-xl flex items-center justify-center mr-4">
<i class="fas fa-boxes text-white"></i>
</div>
<div>
<h2 class="heading-3 mb-1">Product Inventory</h2>
<p class="text-muted">
@if(request()->hasAny(['game', 'stock', 'search']))
{{ $products->count() }} filtered results
@if($products->count() > 0)
<span class="text-white/40">•</span>
<a href="{{ route('products.listOFproduct') }}" class="text-purple-400 hover:text-purple-300 text-sm">
View all products
</a>
@endif
@else
{{ $products->count() }} products in your catalog
@endif
</p>
</div>
</div>
</div>
<!-- Enhanced Search and Filter Section -->
<div class="mb-8">
<form method="GET" action="{{ route('products.listOFproduct') }}" class="space-y-4">
<!-- Search Bar - Full Width -->
<div class="relative">
<input type="text" name="search" value="{{ request('search') }}"
placeholder="🔍 Search products by name or description..."
class="input-field pl-12 pr-4 w-full text-lg py-4 bg-black/40 border-2 border-white/20 focus:border-purple-500/60 rounded-xl">
<i class="fas fa-search absolute left-4 top-1/2 transform -translate-y-1/2 text-white/60 text-lg"></i>
@if(request('search'))
<button type="button" onclick="clearSearch()" class="absolute right-4 top-1/2 transform -translate-y-1/2 text-white/60 hover:text-white">
<i class="fas fa-times"></i>
</button>
@endif
</div>
<!-- Filters Row -->
<div class="flex flex-col sm:flex-row items-center gap-4">
<select name="stock" class="input-field flex-1 min-w-0">
<option value="">📦 All Stock</option>
<option value="in_stock" {{ request('stock') == 'in_stock' ? 'selected' : '' }}>
✅ In Stock
</option>
<option value="low_stock" {{ request('stock') == 'low_stock' ? 'selected' : '' }}>
⚠️ Low Stock
</option>
<option value="out_of_stock" {{ request('stock') == 'out_of_stock' ? 'selected' : '' }}>
❌ Out of Stock
</option>
</select>
<select name="game" class="input-field flex-1 min-w-0">
<option value="">🎮 All Categories</option>
<optgroup label="Main Categories">
<option value="Genshin" {{ request('game') == 'Genshin' ? 'selected' : '' }}>⭐ Genshin Impact</option>
<option value="Starrail" {{ request('game') == 'Starrail' ? 'selected' : '' }}>🚀 Honkai: Star Rail</option>
<option value="WutheringWave" {{ request('game') == 'WutheringWave' ? 'selected' : '' }}>🌊 Wuthering Waves</option>
</optgroup>
<optgroup label="Additional Games">
<option value="ZenlessZoneZero" {{ request('game') == 'ZenlessZoneZero' ? 'selected' : '' }}>🏙️ Zenless Zone Zero</option>
<option value="Arknights" {{ request('game') == 'Arknights' ? 'selected' : '' }}>♞ Arknights</option>
<option value="AzurLane" {{ request('game') == 'AzurLane' ? 'selected' : '' }}>🚢 Azur Lane</option>
</optgroup>
@if(isset($customGames) && $customGames->count() > 0)
<optgroup label="Custom Games">
@foreach($customGames as $customGame)
<option value="{{ $customGame->name }}" {{ request('game') == $customGame->name ? 'selected' : '' }}>
🎮 {{ $customGame->name }}
</option>
@endforeach
</optgroup>
@endif
</select>
<div class="flex items-center gap-2 flex-shrink-0">
<button type="submit" class="btn-primary px-6 py-3">
<i class="fas fa-filter mr-2"></i>Apply Filters
</button>
<a href="{{ route('products.listOFproduct') }}" class="btn-secondary px-4 py-3">
<i class="fas fa-refresh mr-1"></i>Clear
</a>
</div>
</div>
</form>
</div>
@if($products->isEmpty())
<div class="text-center py-16">
<div class="w-20 h-20 bg-gradient-to-r from-gray-600 to-gray-800 rounded-full flex items-center justify-center mx-auto mb-6 opacity-50">
<i class="fas fa-box-open text-3xl text-white"></i>
</div>
<h3 class="heading-3 mb-4">No Products Yet</h3>
<p class="text-muted mb-8">Start building your inventory by adding your first product.</p>
<button class="btn-primary" onclick="document.getElementById('show_category_modal').click()">
<i class="fas fa-plus mr-2"></i>Add Your First Product
</button>
</div>
@else
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 gap-8">
@foreach($products as $product)
<div class="product-card glass-bg border border-white/10 rounded-2xl overflow-hidden transition-all duration-500 hover:border-purple-500/50 hover:shadow-2xl hover:shadow-purple-500/20 group transform hover:scale-105">
<!-- Product Image -->
<div class="relative h-64 overflow-hidden">
<img src="{{ $product->image }}" alt="{{ $product->name }}"
class="w-full h-full object-cover transition-transform duration-500 group-hover:scale-110">
<!-- Gradient Overlay -->
<div class="absolute inset-0 bg-gradient-to-t from-black/90 via-black/30 to-transparent"></div>
<!-- Stock Badge -->
<div class="absolute top-4 right-4">
@if($product->Amount === 0)
<span class="px-4 py-2 rounded-xl text-sm font-semibold bg-red-500/90 text-white border border-red-400/50 shadow-lg backdrop-blur-sm">
<i class="fas fa-times-circle mr-2"></i>Out of Stock
</span>
@elseif($product->Amount <= 5)
<span class="px-4 py-2 rounded-xl text-sm font-semibold bg-orange-500/90 text-white border border-orange-400/50 shadow-lg backdrop-blur-sm animate-pulse">
<i class="fas fa-exclamation-triangle mr-2"></i>{{ $product->Amount }} Left
</span>
@else
<span class="px-4 py-2 rounded-xl text-sm font-semibold bg-green-500/90 text-white border border-green-400/50 shadow-lg backdrop-blur-sm">
<i class="fas fa-check-circle mr-2"></i>In Stock
</span>
@endif
</div>
</div>
<!-- Product Content -->
<div class="p-6">
<!-- Price Display -->
<div class="mb-4">
<div class="bg-black/90 backdrop-blur-sm rounded-xl px-5 py-3 border border-purple-500/30">
<div class="text-xs text-white/60 mb-1">Price</div>
<div class="text-2xl font-bold text-white">
฿{{ number_format($product->price, 2) }}
</div>
</div>
</div>
<!-- Game Category Badge -->
@if($product->game)
<div class="mb-4">
<span class="px-3 py-2 rounded-full text-sm font-semibold
@if($product->game == 'Genshin')
bg-yellow-500/20 text-yellow-300 border border-yellow-500/30
@elseif($product->game == 'Starrail')
bg-purple-500/20 text-purple-300 border border-purple-500/30
@elseif($product->game == 'WutheringWave')
bg-cyan-500/20 text-cyan-300 border border-cyan-500/30
@else
bg-blue-500/20 text-blue-300 border border-blue-500/30
@endif">
@if($product->game == 'Genshin')
<i class="fas fa-star mr-2"></i>Genshin Impact
@elseif($product->game == 'Starrail')
<i class="fas fa-rocket mr-2"></i>Honkai: Star Rail
@elseif($product->game == 'WutheringWave')
<i class="fas fa-wave-square mr-2"></i>Wuthering Waves
@else
<i class="fas fa-gamepad mr-2"></i>{{ $product->game }}
@endif
</span>
</div>
@endif
<!-- Product Title -->
<h3 class="text-xl font-bold text-white mb-3 group-hover:text-purple-300 transition-colors duration-300">
{{ $product->name }}
</h3>
<!-- Product Description -->
<p class="text-white/70 text-sm mb-6 line-clamp-3 leading-relaxed">
{{ $product->description }}
</p>
<!-- Action Buttons -->
<div class="flex items-center space-x-3">
<button class="flex-1 py-3 px-4 bg-gradient-to-r from-blue-600 to-purple-600 hover:from-blue-500 hover:to-purple-500 text-white rounded-xl font-semibold transition-all duration-300 shadow-lg hover:shadow-purple-500/30 transform hover:scale-105" onclick="editProduct({{ $product->id }}, '{{ addslashes($product->name) }}', '{{ addslashes($product->description) }}', {{ $product->price }}, {{ $product->Amount }}, '{{ $product->game }}', '{{ $product->image }}')">
<i class="fas fa-edit mr-2"></i>Edit
</button>
<form action="{{ route('products.destroy', $product->id) }}" method="POST" class="inline">
@csrf
@method('DELETE')
<button type="submit" class="py-3 px-4 bg-gradient-to-r from-red-600 to-red-700 hover:from-red-500 hover:to-red-600 text-white rounded-xl font-semibold transition-all duration-300 shadow-lg hover:shadow-red-500/30 transform hover:scale-105"
onclick="return confirm('Are you sure you want to delete this product?')">
<i class="fas fa-trash mr-2"></i>Delete
</button>
</form>
</div>
</div>
</div>
@endforeach
</div>
@endif
</div>
</div>
</div>
<!-- Add/Edit Product Modal -->
<div id="productModal" class="fixed inset-0 bg-black/50 backdrop-blur-sm hidden items-center justify-center z-50 p-4">
<div class="card max-w-2xl w-full max-h-[90vh] flex flex-col">
<div class="flex-shrink-0 flex items-center justify-between mb-6">
<h3 class="heading-3" id="modalTitle">Add New Product</h3>
<button onclick="closeModal()" class="text-white/60 hover:text-white text-2xl transition-colors">
<i class="fas fa-times"></i>
</button>
</div>
<div class="flex-1 overflow-y-auto custom-scrollbar pr-2">
<form id="productForm" method="POST" enctype="multipart/form-data" class="space-y-6">
@csrf
<div id="methodField"></div>
<div>
<label class="block text-sm font-medium text-white mb-2">Product Name</label>
<input type="text" name="name" id="productName" required class="input-field">
</div>
<div>
<label class="block text-sm font-medium text-white mb-2">Description</label>
<textarea name="description" id="productDescription" rows="3" class="input-field resize-none"></textarea>
</div>
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
<div>
<label class="block text-sm font-medium text-white mb-2">Price (฿)</label>
<input type="number" name="price" id="productPrice" step="0.01" required class="input-field">
</div>
<div>
<label class="block text-sm font-medium text-white mb-2">Stock Amount</label>
<input type="number" name="Amount" id="productAmount" required class="input-field">
</div>
</div>
<div>
<label class="block text-sm font-medium text-white mb-2">Game Category</label>
<select name="game" id="productGame" class="input-field">
<option value="">Select Game</option>
<optgroup label="Main Categories">
<option value="Genshin">Genshin Impact</option>
<option value="Starrail">Honkai: Star Rail</option>
<option value="WutheringWave">Wuthering Waves</option>
</optgroup>
<optgroup label="Additional Games">
<option value="ZenlessZoneZero">Zenless Zone Zero</option>
<option value="Arknights">Arknights</option>
<option value="AzurLane">Azur Lane</option>
</optgroup>
@if(isset($customGames) && $customGames->count() > 0)
<optgroup label="Custom Games" id="existingCustomGames">
@foreach($customGames as $customGame)
<option value="{{ $customGame->name }}">{{ $customGame->name }}</option>
@endforeach
</optgroup>
@endif
</select>
</div>
<!-- Product Specifications Section -->
<div class="border-t border-white/10 pt-6">
<h4 class="text-lg font-semibold text-white mb-4 flex items-center">
<i class="fas fa-cog mr-2 text-purple-400"></i>
Product Specifications
</h4>
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
<div>
<label class="block text-sm font-medium text-white mb-2">Product Type</label>
<select name="product_type" id="productType" class="input-field">
<option value="Digital Account">Digital Account</option>
<option value="Game Currency">Game Currency</option>
<option value="Items">Items</option>
<option value="Boost Service">Boost Service</option>
</select>
</div>
<div>
<label class="block text-sm font-medium text-white mb-2">Platform</label>
<select name="platform" id="productPlatform" class="input-field">
<option value="Multi-Platform">Multi-Platform</option>
<option value="PC">PC</option>
<option value="Mobile">Mobile</option>
<option value="PlayStation">PlayStation</option>
<option value="Xbox">Xbox</option>
</select>
</div>
<div>
<label class="block text-sm font-medium text-white mb-2">Region</label>
<select name="region" id="productRegion" class="input-field">
<option value="Global">Global</option>
<option value="Asia">Asia</option>
<option value="Europe">Europe</option>
<option value="America">America</option>
<option value="China">China</option>
</select>
</div>
<div>
<label class="block text-sm font-medium text-white mb-2">Delivery Method</label>
<select name="delivery_method" id="deliveryMethod" class="input-field">
<option value="Instant Digital">Instant Digital</option>
<option value="Manual Delivery">Manual Delivery</option>
<option value="Email Delivery">Email Delivery</option>
</select>
</div>
<div>
<label class="block text-sm font-medium text-white mb-2">Warranty Period</label>
<select name="warranty" id="productWarranty" class="input-field">
<option value="Lifetime Support">Lifetime Support</option>
<option value="1 Year">1 Year</option>
<option value="6 Months">6 Months</option>
<option value="3 Months">3 Months</option>
<option value="1 Month">1 Month</option>
<option value="No Warranty">No Warranty</option>
</select>
</div>
<div>
<label class="block text-sm font-medium text-white mb-2">Support Level</label>
<select name="support_level" id="supportLevel" class="input-field">
<option value="24/7 Available">24/7 Available</option>
<option value="Business Hours">Business Hours</option>
<option value="Email Only">Email Only</option>
<option value="Limited Support">Limited Support</option>
</select>
</div>
</div>
<div class="mt-4">
<label class="block text-sm font-medium text-white mb-2">Additional Features</label>
<textarea name="features" id="productFeatures" rows="3" placeholder="List key features, benefits, or special notes about this product..." class="input-field resize-none"></textarea>
</div>
</div>
<div>
<label class="block text-sm font-medium text-white mb-2">Product Image</label>
<div id="currentImagePreview" class="hidden mb-4">
<div class="text-sm text-white/70 mb-2">Current Image:</div>
<img id="currentImage" src="" alt="Current product image"
class="w-32 h-32 object-cover rounded-lg border border-white/20">
</div>
<!-- Custom File Upload -->
<div class="relative">
<div id="fileUploadArea" class="border-2 border-dashed border-white/20 rounded-xl p-6 text-center hover:border-purple-400/50 transition-all duration-300 cursor-pointer bg-black/20 hover:bg-black/30">
<div id="uploadContent">
<i class="fas fa-cloud-upload-alt text-3xl text-white/40 mb-3"></i>
<div class="text-white/80 mb-2">
<span class="text-purple-400 hover:text-purple-300 font-medium">Choose file</span>
<span class="text-white/60"> or drag and drop</span>
</div>
<p class="text-xs text-white/50">PNG, JPG, GIF up to 10MB</p>
</div>
<div id="fileInfo" class="hidden">
<i class="fas fa-file-image text-2xl text-green-400 mb-2"></i>
<div class="text-green-400 font-medium" id="fileName"></div>
<div class="text-white/60 text-sm" id="fileSize"></div>
<button type="button" id="removeFile" class="mt-2 text-red-400 hover:text-red-300 text-sm transition-colors">
<i class="fas fa-times mr-1"></i>Remove
</button>
</div>
</div>
<input type="file" name="image" id="productImage" accept="image/*" class="absolute inset-0 w-full h-full opacity-0 cursor-pointer">
</div>
<p class="text-xs text-white/50 mt-2">Leave empty to keep current image</p>
</div>
</form>
</div>
<div class="flex-shrink-0 flex items-center space-x-4 pt-6 border-t border-white/10 mt-6">
<button type="submit" form="productForm" class="btn-primary flex-1">
<i class="fas fa-save mr-2"></i>Save Product
</button>
<button type="button" onclick="closeModal()" class="btn-secondary">
Cancel
</button>
</div>
</div>
</div>
<!-- Category Selection Modal -->
<div id="categoryModal" class="fixed inset-0 bg-black/50 backdrop-blur-sm hidden items-center justify-center z-50 p-4">
<div class="card max-w-2xl w-full">
<div class="flex items-center justify-between mb-6">
<h3 class="heading-3">Choose Game Category</h3>
<button onclick="closeCategoryModal()" class="text-white/60 hover:text-white text-2xl transition-colors">
<i class="fas fa-times"></i>
</button>
</div>
<p class="text-white/70 mb-8">Select the game category for your new product:</p>
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
<button onclick="openNewProductModal('Genshin')" class="p-6 bg-gradient-to-r from-yellow-500/20 to-orange-500/20 border border-yellow-500/30 rounded-xl text-left hover:border-yellow-500/50 transition-all duration-300 group">
<div class="flex items-center">
<div class="w-12 h-12 bg-gradient-to-r from-yellow-500 to-orange-500 rounded-lg flex items-center justify-center mr-4 group-hover:scale-110 transition-transform duration-300">
<i class="fas fa-star text-white text-xl"></i>
</div>
<div>
<div class="text-white font-bold text-lg">Genshin Impact</div>
<div class="text-yellow-300 text-sm">Add Genshin product</div>
</div>
</div>
</button>
<button onclick="openNewProductModal('Starrail')" class="p-6 bg-gradient-to-r from-purple-500/20 to-pink-500/20 border border-purple-500/30 rounded-xl text-left hover:border-purple-500/50 transition-all duration-300 group">
<div class="flex items-center">
<div class="w-12 h-12 bg-gradient-to-r from-purple-500 to-pink-500 rounded-lg flex items-center justify-center mr-4 group-hover:scale-110 transition-transform duration-300">
<i class="fas fa-rocket text-white text-xl"></i>
</div>
<div>
<div class="text-white font-bold text-lg">Honkai: Star Rail</div>
<div class="text-purple-300 text-sm">Add Star Rail product</div>
</div>
</div>
</button>
<button onclick="openNewProductModal('WutheringWave')" class="p-6 bg-gradient-to-r from-cyan-500/20 to-blue-500/20 border border-cyan-500/30 rounded-xl text-left hover:border-cyan-500/50 transition-all duration-300 group">
<div class="flex items-center">
<div class="w-12 h-12 bg-gradient-to-r from-cyan-500 to-blue-500 rounded-lg flex items-center justify-center mr-4 group-hover:scale-110 transition-transform duration-300">
<i class="fas fa-wave-square text-white text-xl"></i>
</div>
<div>
<div class="text-white font-bold text-lg">Wuthering Waves</div>
<div class="text-cyan-300 text-sm">Add Wuthering product</div>
</div>
</div>
</button>
<button onclick="showOtherGamesModal()" class="p-6 bg-gradient-to-r from-gray-500/20 to-slate-500/20 border border-gray-500/30 rounded-xl text-left hover:border-gray-500/50 transition-all duration-300 group">
<div class="flex items-center">
<div class="w-12 h-12 bg-gradient-to-r from-gray-500 to-slate-500 rounded-lg flex items-center justify-center mr-4 group-hover:scale-110 transition-transform duration-300">
<i class="fas fa-plus text-white text-xl"></i>
</div>
<div>
<div class="text-white font-bold text-lg">Other Games</div>
<div class="text-gray-300 text-sm">More game categories</div>
</div>
</div>
</button>
</div>
<!-- Quick Custom Game Section -->
<div class="mt-8 pt-6 border-t border-white/10">
<div class="flex items-center justify-between mb-4">
<h4 class="text-white font-semibold">Quick Add Custom Game</h4>
<i class="fas fa-gamepad text-purple-400"></i>
</div>
<button onclick="showQuickCustomGameInput()" class="w-full p-4 bg-gradient-to-r from-purple-500/10 to-blue-500/10 border-2 border-dashed border-purple-500/30 rounded-xl text-left hover:border-purple-500/50 hover:bg-purple-500/20 transition-all duration-300 group">
<div class="flex items-center justify-center">
<div class="w-10 h-10 border-2 border-dashed border-purple-400/50 rounded-lg flex items-center justify-center mr-3 group-hover:scale-110 group-hover:border-purple-400/70 transition-all duration-300">
<i class="fas fa-plus text-purple-400 group-hover:text-purple-300"></i>
</div>
<div class="text-center">
<div class="text-white font-medium">Add Custom Game Category</div>
<div class="text-purple-300 text-sm">Create your own game category</div>
</div>
</div>
</button>
<!-- Quick Custom Game Input (Hidden by default) -->
<div id="quickCustomGameInput" class="hidden mt-4 p-4 bg-gradient-to-r from-purple-500/10 to-blue-500/10 border border-purple-500/30 rounded-xl">
<div class="space-y-3">
<input type="text" id="quickCustomGameName" placeholder="Enter game name (e.g., Final Fantasy XIV, Valorant...)"
class="input-field w-full" maxlength="50"
onkeypress="if(event.key==='Enter') createQuickCustomGame()">
<div class="flex items-center space-x-2">
<button onclick="createQuickCustomGame()" class="btn-primary px-6 py-2 text-sm">
<i class="fas fa-check mr-1"></i>Create
</button>
<button onclick="hideQuickCustomGameInput()" class="btn-secondary px-4 py-2 text-sm">
<i class="fas fa-times mr-1"></i>Cancel
</button>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- Other Games Selection Modal -->
<div id="otherGamesModal" class="fixed inset-0 bg-black/50 backdrop-blur-sm hidden items-center justify-center z-50 p-4">
<div class="card max-w-3xl w-full">
<div class="flex items-center justify-between mb-6">
<h3 class="heading-3">Choose Additional Game Category</h3>
<button onclick="closeOtherGamesModal()" class="text-white/60 hover:text-white text-2xl transition-colors">
<i class="fas fa-times"></i>
</button>
</div>
<p class="text-white/70 mb-8">Select from additional game categories:</p>
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
<button onclick="openNewProductModal('ZenlessZoneZero')" class="p-6 bg-gradient-to-r from-red-500/20 to-pink-500/20 border border-red-500/30 rounded-xl text-left hover:border-red-500/50 transition-all duration-300 group">
<div class="flex flex-col items-center text-center">
<div class="w-12 h-12 bg-gradient-to-r from-red-500 to-pink-500 rounded-lg flex items-center justify-center mb-3 group-hover:scale-110 transition-transform duration-300">
<i class="fas fa-city text-white text-xl"></i>
</div>
<div class="text-white font-bold text-lg mb-1">Zenless Zone Zero</div>
<div class="text-red-300 text-sm">Urban fantasy RPG</div>
</div>
</button>
<button onclick="openNewProductModal('Arknights')" class="p-6 bg-gradient-to-r from-indigo-500/20 to-purple-500/20 border border-indigo-500/30 rounded-xl text-left hover:border-indigo-500/50 transition-all duration-300 group">
<div class="flex flex-col items-center text-center">
<div class="w-12 h-12 bg-gradient-to-r from-indigo-500 to-purple-500 rounded-lg flex items-center justify-center mb-3 group-hover:scale-110 transition-transform duration-300">
<i class="fas fa-chess-knight text-white text-xl"></i>
</div>
<div class="text-white font-bold text-lg mb-1">Arknights</div>
<div class="text-indigo-300 text-sm">Tower defense strategy</div>
</div>
</button>
<button onclick="openNewProductModal('AzurLane')" class="p-6 bg-gradient-to-r from-blue-500/20 to-teal-500/20 border border-blue-500/30 rounded-xl text-left hover:border-blue-500/50 transition-all duration-300 group">
<div class="flex flex-col items-center text-center">
<div class="w-12 h-12 bg-gradient-to-r from-blue-500 to-teal-500 rounded-lg flex items-center justify-center mb-3 group-hover:scale-110 transition-transform duration-300">
<i class="fas fa-ship text-white text-xl"></i>
</div>
<div class="text-white font-bold text-lg mb-1">Azur Lane</div>
<div class="text-blue-300 text-sm">Naval warfare RPG</div>
</div>
</button>
@if(isset($customGames))
@foreach($customGames as $customGame)
@php
// Use stored styling from database
$gameIcon = $customGame->icon;
$gameGradient = $customGame->color_gradient;
// Extract color names from gradient for consistent theming
$gradientParts = explode(' ', $gameGradient);
$primaryColor = str_replace(['from-', '-500'], '', $gradientParts[0] ?? 'purple');
// Map to predefined color classes
$colorMap = [
'red' => ['from-red-500/20 to-pink-500/20', 'border-red-500/30', 'hover:border-red-500/50', $gameGradient, 'text-red-300'],
'pink' => ['from-pink-500/20 to-rose-500/20', 'border-pink-500/30', 'hover:border-pink-500/50', $gameGradient, 'text-pink-300'],
'rose' => ['from-rose-500/20 to-pink-500/20', 'border-rose-500/30', 'hover:border-rose-500/50', $gameGradient, 'text-rose-300'],
'purple' => ['from-purple-500/20 to-blue-500/20', 'border-purple-500/30', 'hover:border-purple-500/50', $gameGradient, 'text-purple-300'],
'blue' => ['from-blue-500/20 to-indigo-500/20', 'border-blue-500/30', 'hover:border-blue-500/50', $gameGradient, 'text-blue-300'],
'green' => ['from-green-500/20 to-teal-500/20', 'border-green-500/30', 'hover:border-green-500/50', $gameGradient, 'text-green-300'],
'orange' => ['from-orange-500/20 to-red-500/20', 'border-orange-500/30', 'hover:border-orange-500/50', $gameGradient, 'text-orange-300'],
'yellow' => ['from-yellow-500/20 to-orange-500/20', 'border-yellow-500/30', 'hover:border-yellow-500/50', $gameGradient, 'text-yellow-300'],
'teal' => ['from-teal-500/20 to-cyan-500/20', 'border-teal-500/30', 'hover:border-teal-500/50', $gameGradient, 'text-teal-300'],
'cyan' => ['from-cyan-500/20 to-blue-500/20', 'border-cyan-500/30', 'hover:border-cyan-500/50', $gameGradient, 'text-cyan-300'],
'indigo' => ['from-indigo-500/20 to-purple-500/20', 'border-indigo-500/30', 'hover:border-indigo-500/50', $gameGradient, 'text-indigo-300'],
'violet' => ['from-violet-500/20 to-purple-500/20', 'border-violet-500/30', 'hover:border-violet-500/50', $gameGradient, 'text-violet-300'],
'emerald' => ['from-emerald-500/20 to-green-500/20', 'border-emerald-500/30', 'hover:border-emerald-500/50', $gameGradient, 'text-emerald-300']
];
$gameColor = $colorMap[$primaryColor] ?? $colorMap['purple'];
@endphp
<div class="relative custom-game-card">
<button onclick="openNewProductModal('{{ $customGame->name }}')" class="w-full p-6 bg-gradient-to-r {{ $gameColor[0] }} border {{ $gameColor[1] }} rounded-xl text-left {{ $gameColor[2] }} transition-all duration-300 group">
<div class="flex flex-col items-center text-center">
<div class="w-12 h-12 bg-gradient-to-r {{ $gameColor[3] }} rounded-lg flex items-center justify-center mb-3 group-hover:scale-110 transition-transform duration-300">
<i class="{{ $gameIcon }} text-white text-xl"></i>
</div>
<div class="text-white font-bold text-lg mb-1">{{ $customGame->name }}</div>
<div class="{{ $gameColor[4] }} text-sm">Custom game</div>
</div>
</button>
<!-- Delete button (hidden by default) -->
<button onclick="deleteCustomGame('{{ $customGame->name }}')" class="delete-btn absolute -top-2 -right-2 w-8 h-8 bg-red-500 hover:bg-red-600 text-white rounded-full flex items-center justify-center opacity-0 invisible transition-all duration-300 transform scale-0 z-10 shadow-lg">
<i class="fas fa-minus text-sm"></i>
</button>
</div>
@endforeach
@endif
<button onclick="showDeleteCustomGameInput();" class="p-6 bg-transparent border-2 border-dashed border-red-400/40 rounded-xl text-left hover:border-red-400/60 hover:bg-red-500/5 transition-all duration-300 group">
<div class="flex flex-col items-center text-center">
<div class="w-16 h-16 border-2 border-dashed border-red-400/40 rounded-lg flex items-center justify-center mb-3 group-hover:scale-110 group-hover:border-red-400/60 transition-all duration-300">
<i class="fas fa-trash text-red-400/70 text-2xl group-hover:text-red-400"></i>
</div>
<div class="text-red-400/80 font-bold text-lg mb-1 group-hover:text-red-400">Delete Custom Game</div>
<div class="text-red-400/50 text-sm group-hover:text-red-400/70">Remove category</div>
</div>
</button>
</div>
<!-- Custom Game Input Section (Hidden by default) -->
<div id="customGameInput" class="hidden mt-8 p-8 bg-gradient-to-r from-purple-500/10 to-blue-500/10 border border-purple-500/30 rounded-2xl">
<h4 class="text-white font-bold text-xl mb-6 flex items-center">
<i class="fas fa-edit mr-3 text-purple-400"></i>
Enter Custom Game Category
</h4>
<div class="space-y-4">
<input type="text" id="customGameName" placeholder="e.g., Final Fantasy XIV, League of Legends, Valorant..."
class="input-field w-full text-lg py-4 px-6" maxlength="50"
onkeypress="if(event.key==='Enter') createCustomGame()">
<div class="flex items-center justify-between">
<p class="text-white/60 text-sm flex items-center">
<i class="fas fa-info-circle mr-2"></i>
This will create a new game category with random colors and icon
</p>
<div class="flex items-center space-x-3">
<button onclick="createCustomGame();" class="btn-primary px-8 py-3">
<i class="fas fa-check mr-2"></i>Create Category
</button>
<button onclick="hideCustomGameInput()" class="btn-secondary px-6 py-3">
<i class="fas fa-times mr-2"></i>Cancel
</button>
</div>
</div>
</div>
</div>
<div class="mt-6 pt-6 border-t border-white/10">
<button onclick="backToCategoryModal()" class="btn-secondary">
<i class="fas fa-arrow-left mr-2"></i>Back to Main Categories
</button>
</div>
</div>
</div>
<!-- Custom Game Success Popup -->
<div id="customGameSuccessModal" class="fixed inset-0 bg-black/50 backdrop-blur-sm hidden items-center justify-center z-50 p-4">
<div class="card max-w-md w-full">
<div class="text-center">
<div class="w-16 h-16 bg-gradient-to-r from-green-500 to-emerald-500 rounded-full flex items-center justify-center mx-auto mb-4 animate-pulse">
<i class="fas fa-check text-white text-2xl"></i>
</div>
<h3 class="heading-3 mb-2 text-green-400">Custom Game Added!</h3>
<p class="text-white/70 mb-6">
<strong class="text-white"><span id="customGameSuccessName"></span></strong> has been successfully added to your game categories.
</p>
<div class="space-y-3">
<h4 class="text-white font-semibold mb-4 flex items-center justify-center">
<i class="fas fa-arrow-right mr-2 text-purple-400"></i>
What's next?
</h4>
<button id="addItemForGame" class="btn-primary w-full py-3 text-lg font-semibold hover:scale-105 transition-transform">
<i class="fas fa-plus mr-2"></i>Add Item for <span id="gameNameInButton" class="font-bold"></span>
</button>
<button onclick="showAddMoreCategory()" class="btn-secondary w-full py-3 hover:scale-105 transition-transform">
<i class="fas fa-gamepad mr-2"></i>Add More Category
</button>
<button onclick="closeCustomGameSuccessModal()" class="text-white/60 hover:text-white transition-colors py-2 hover:scale-105">
<i class="fas fa-times mr-2"></i>Close
</button>
</div>
</div>
</div>
</div>
<style>
/* Custom Scrollbar */
.custom-scrollbar::-webkit-scrollbar {
width: 8px;
}
.custom-scrollbar::-webkit-scrollbar-track {
background: rgba(255, 255, 255, 0.1);
border-radius: 4px;
}
.custom-scrollbar::-webkit-scrollbar-thumb {
background: rgba(102, 126, 234, 0.6);
border-radius: 4px;
transition: background 0.3s ease;
}
.custom-scrollbar::-webkit-scrollbar-thumb:hover {
background: rgba(102, 126, 234, 0.8);
}
/* Firefox scrollbar */
.custom-scrollbar {
scrollbar-width: thin;
scrollbar-color: rgba(102, 126, 234, 0.6) rgba(255, 255, 255, 0.1);
}
/* Dropdown z-index fix */
#category_dropdown {
z-index: 99999 !important;
position: fixed !important;
top: auto !important;
right: auto !important;
}
/* Ensure parent container doesn't clip */
.relative {
position: relative;
z-index: auto;
}
/* Force dropdown above everything */
#category_dropdown {
position: fixed !important;
z-index: 99999 !important;
}
/* Dropdown animation */
#category_dropdown {
transform: translateY(-10px);
opacity: 0;
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
pointer-events: none;
}
#category_dropdown:not(.hidden) {
transform: translateY(0);
opacity: 1;
pointer-events: auto;
}
/* File upload animations */
#fileUploadArea {
transition: all 0.3s ease;
}
#fileUploadArea:hover {
transform: translateY(-2px);
box-shadow: 0 8px 25px rgba(102, 126, 234, 0.2);
}
#fileUploadArea.dragover {
border-color: rgba(102, 126, 234, 0.8) !important;
background: rgba(102, 126, 234, 0.1) !important;
transform: scale(1.02);
}
/* Custom Game Delete Mode Styles */
.custom-game-card.delete-mode {
animation: gentleShake 2s ease-in-out infinite;
filter: brightness(0.8) saturate(0.7);
}
.custom-game-card.delete-mode .delete-btn {
opacity: 1 !important;
visibility: visible !important;
transform: scale(1) !important;
animation: pulseGlow 1.5s ease-in-out infinite;
}
@keyframes gentleShake {
0%, 100% { transform: translateX(0); }
25% { transform: translateX(-1px); }
75% { transform: translateX(1px); }
}
@keyframes pulseGlow {
0%, 100% {
box-shadow: 0 0 5px rgba(239, 68, 68, 0.5);
transform: scale(1);
}
50% {
box-shadow: 0 0 15px rgba(239, 68, 68, 0.8);
transform: scale(1.05);
}
}
/* Standard effects for custom games - consistent with other games */
.custom-game-card:not(.delete-mode) {
transition: all 0.3s ease;
}
/* Reduced animation intensity for better UX */
.custom-game-card button {
transition: all 0.2s ease;
}
.custom-game-card button:hover {
transform: scale(1.02);
}
/* Custom notification styles */
.custom-notification {
backdrop-filter: blur(10px);
border: 1px solid rgba(255, 255, 255, 0.1);
}
/* Delete mode overlay */
.delete-mode-overlay {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: rgba(0, 0, 0, 0.3);
z-index: 5;
pointer-events: none;
}
</style>
<script>
// Search functionality
function clearSearch() {
const searchInput = document.querySelector('input[name="search"]');
searchInput.value = '';
searchInput.form.submit();
}
// Auto-submit search on Enter key
document.querySelector('input[name="search"]').addEventListener('keypress', function(e) {
if (e.key === 'Enter') {
e.preventDefault();
this.form.submit();
}
});
// Modal functions
function openModal(title = 'Add New Product', action = '{{ route("products.store") }}', method = 'POST') {
document.getElementById('modalTitle').textContent = title;
document.getElementById('productForm').action = action;
document.getElementById('methodField').innerHTML = method === 'PUT' ? '@method("PUT")' : '';
document.getElementById('productModal').classList.remove('hidden');
document.getElementById('productModal').classList.add('flex');
}
function closeModal() {
document.getElementById('productModal').classList.add('hidden');
document.getElementById('productModal').classList.remove('flex');
document.getElementById('productForm').reset();
// Hide current image preview
document.getElementById('currentImagePreview').classList.add('hidden');
// Reset image field to required for new products
document.getElementById('productImage').setAttribute('required', 'required');
}
function editProduct(id, name, description, price, amount, game, image, productType = 'Digital Account', platform = 'Multi-Platform', region = 'Global', deliveryMethod = 'Instant Digital', warranty = 'Lifetime Support', supportLevel = '24/7 Available', features = '') {
// Populate form with existing product data
document.getElementById('productName').value = name || '';
document.getElementById('productDescription').value = description || '';
document.getElementById('productPrice').value = price || '';
document.getElementById('productAmount').value = amount || '';
document.getElementById('productGame').value = game || '';
// Populate specification fields
document.getElementById('productType').value = productType || 'Digital Account';
document.getElementById('productPlatform').value = platform || 'Multi-Platform';
document.getElementById('productRegion').value = region || 'Global';
document.getElementById('deliveryMethod').value = deliveryMethod || 'Instant Digital';
document.getElementById('productWarranty').value = warranty || 'Lifetime Support';
document.getElementById('supportLevel').value = supportLevel || '24/7 Available';
document.getElementById('productFeatures').value = features || '';
// Show current image if exists
const currentImagePreview = document.getElementById('currentImagePreview');
const currentImage = document.getElementById('currentImage');
if (image) {
currentImage.src = image;
currentImagePreview.classList.remove('hidden');
} else {
currentImagePreview.classList.add('hidden');
}
// Clear file input for new image upload
document.getElementById('productImage').value = '';
// Make image field optional for editing
document.getElementById('productImage').removeAttribute('required');
openModal('Edit Product', `/products/${id}`, 'PUT');
}
// Show category selection modal
document.getElementById('show_category_modal').addEventListener('click', () => {
console.log('Category modal button clicked');
const categoryModal = document.getElementById('categoryModal');
if (categoryModal) {
categoryModal.classList.remove('hidden');
categoryModal.classList.add('flex');
console.log('Category modal shown');
} else {
console.error('Category modal not found');
}
});
// Close category modal
function closeCategoryModal() {
document.getElementById('categoryModal').classList.add('hidden');
document.getElementById('categoryModal').classList.remove('flex');
}
// Close category modal when clicking outside
document.getElementById('categoryModal').addEventListener('click', (e) => {
if (e.target === e.currentTarget) {
closeCategoryModal();
}
});
// Show other games modal
function showOtherGamesModal() {
console.log('showOtherGamesModal called');
closeCategoryModal();
const otherGamesModal = document.getElementById('otherGamesModal');
if (otherGamesModal) {
otherGamesModal.classList.remove('hidden');
otherGamesModal.classList.add('flex');
console.log('Other games modal shown');
} else {
console.error('Other games modal not found');
}
}
// Close other games modal
function closeOtherGamesModal() {
document.getElementById('otherGamesModal').classList.add('hidden');
document.getElementById('otherGamesModal').classList.remove('flex');
}
// Back to main category modal
function backToCategoryModal() {
closeOtherGamesModal();
document.getElementById('categoryModal').classList.remove('hidden');
document.getElementById('categoryModal').classList.add('flex');
}
// Close other games modal when clicking outside
document.getElementById('otherGamesModal').addEventListener('click', (e) => {
if (e.target === e.currentTarget) {
closeOtherGamesModal();
}
});
// Show custom game input
function showCustomGameInput() {
console.log('showCustomGameInput called'); // Debug log
const customGameInput = document.getElementById('customGameInput');
const customGameName = document.getElementById('customGameName');
if (!customGameInput) {
console.error('customGameInput element not found');
alert('Error: Custom game input section not found. Please refresh the page and try again.');
return;
}
if (!customGameName) {
console.error('customGameName element not found');
alert('Error: Custom game name input not found. Please refresh the page and try again.');
return;
}
// Show the input section
customGameInput.classList.remove('hidden');
// Clear any previous input
customGameName.value = '';
// Focus on the input with a small delay to ensure visibility
setTimeout(() => {
customGameName.focus();
customGameName.select(); // Select any existing text
}, 150);
console.log('Custom game input shown and focused'); // Debug log
}
// Hide custom game input
function hideCustomGameInput() {
console.log('hideCustomGameInput called'); // Debug log
const customGameInput = document.getElementById('customGameInput');
const customGameName = document.getElementById('customGameName');
if (customGameInput) {
customGameInput.classList.add('hidden');
console.log('Custom game input hidden'); // Debug log
}
if (customGameName) {
customGameName.value = '';
console.log('Custom game name input cleared'); // Debug log
}
}
// Show delete custom game mode
function showDeleteCustomGameInput() {
console.log('showDeleteCustomGameInput called');
// Add delete mode to all custom game cards
const customGameCards = document.querySelectorAll('.custom-game-card');
customGameCards.forEach(card => {
card.classList.add('delete-mode');
});
// Show overlay message
showDeleteModeMessage();
console.log('Delete mode activated for', customGameCards.length, 'custom games');
}
// Hide delete custom game mode
function hideDeleteCustomGameInput() {
console.log('hideDeleteCustomGameInput called');
// Remove delete mode from all custom game cards
const customGameCards = document.querySelectorAll('.custom-game-card');
customGameCards.forEach(card => {
card.classList.remove('delete-mode');
});
// Hide overlay message
hideDeleteModeMessage();
console.log('Delete mode deactivated');
}
// Show delete mode message
function showDeleteModeMessage() {
// Create overlay if it doesn't exist
let overlay = document.getElementById('deleteModeOverlay');
if (!overlay) {
overlay = document.createElement('div');
overlay.id = 'deleteModeOverlay';
overlay.className = 'fixed top-0 left-0 right-0 bg-red-500/90 text-white text-center py-3 z-50 transform -translate-y-full transition-transform duration-300';
overlay.innerHTML = `
<div class="flex items-center justify-center space-x-4">
<i class="fas fa-trash text-xl"></i>
<span class="font-semibold">Delete Mode Active - Click minus buttons to delete custom games</span>
<button onclick="hideDeleteCustomGameInput()" class="bg-white/20 hover:bg-white/30 px-4 py-1 rounded-full text-sm transition-colors">
<i class="fas fa-times mr-1"></i>Cancel
</button>
</div>
`;
document.body.appendChild(overlay);
}
// Show overlay
setTimeout(() => {
overlay.classList.remove('-translate-y-full');
overlay.classList.add('translate-y-0');
}, 100);
}
// Hide delete mode message
function hideDeleteModeMessage() {
const overlay = document.getElementById('deleteModeOverlay');
if (overlay) {
overlay.classList.remove('translate-y-0');
overlay.classList.add('-translate-y-full');
}
}
// Delete custom game
async function deleteCustomGame(gameName) {
if (confirm(`Are you sure you want to delete the custom game "${gameName}"?\n\nThis will remove it from all dropdowns. If any products are using this category, you'll need to reassign them first.`)) {
console.log('Deleting custom game:', gameName);
try {
// Show loading state
const deleteBtn = event.target.closest('.delete-btn');
if (deleteBtn) {
deleteBtn.innerHTML = '<i class="fas fa-spinner fa-spin text-sm"></i>';
deleteBtn.disabled = true;
}
// Call backend API
const response = await fetch(`/custom-games/${encodeURIComponent(gameName)}`, {
method: 'DELETE',
headers: {
'X-CSRF-TOKEN': document.querySelector('meta[name="csrf-token"]')?.getAttribute('content') || '',
'Content-Type': 'application/json',
'Accept': 'application/json'
}
});
const result = await response.json();
if (result.success) {
// Remove from product game select dropdown
const gameSelect = document.getElementById('productGame');
if (gameSelect) {
const optionToRemove = Array.from(gameSelect.options).find(option => option.value === gameName);
if (optionToRemove) {
optionToRemove.remove();
console.log('Removed from product select:', gameName);
}
// Check if Custom Games optgroup is empty and remove it
const customOptgroup = gameSelect.querySelector('optgroup[label="Custom Games"]');
if (customOptgroup && customOptgroup.children.length === 0) {
customOptgroup.remove();
console.log('Removed empty Custom Games optgroup');
}
}
// Remove from localStorage
localStorage.removeItem(`customGame_${gameName}`);
// Remove the card from the modal with animation
const customGameCards = document.querySelectorAll('.custom-game-card');
customGameCards.forEach(card => {
const button = card.querySelector('button[onclick*="' + gameName + '"]');
if (button) {
// Add fade out animation
card.style.transition = 'all 0.3s ease';
card.style.transform = 'scale(0.8)';
card.style.opacity = '0';
setTimeout(() => {
card.remove();
console.log('Removed card for:', gameName);
// Check if there are any custom games left
const remainingCards = document.querySelectorAll('.custom-game-card');
if (remainingCards.length === 0) {
hideDeleteCustomGameInput();
}
}, 300);
}
});
// Show success message with better styling
showNotification(result.message, 'success');
} else {
// Show error message
showNotification(result.message, 'error');
// Reset delete button
if (deleteBtn) {
deleteBtn.innerHTML = '<i class="fas fa-minus text-sm"></i>';
deleteBtn.disabled = false;
}
}
} catch (error) {
console.error('Error deleting custom game:', error);
showNotification('Failed to delete custom game. Please try again.', 'error');
// Reset delete button
const deleteBtn = event.target.closest('.delete-btn');
if (deleteBtn) {
deleteBtn.innerHTML = '<i class="fas fa-minus text-sm"></i>';
deleteBtn.disabled = false;
}
}
}
}
// Show notification function
function showNotification(message, type = 'info') {
// Remove existing notifications
const existingNotifications = document.querySelectorAll('.custom-notification');
existingNotifications.forEach(notification => notification.remove());
// Create notification element
const notification = document.createElement('div');
notification.className = `custom-notification fixed top-4 right-4 z-50 p-4 rounded-lg shadow-lg transform translate-x-full transition-all duration-300 ${
type === 'success' ? 'bg-green-500/90 text-white' :
type === 'error' ? 'bg-red-500/90 text-white' :
'bg-blue-500/90 text-white'
}`;
notification.innerHTML = `
<div class="flex items-center space-x-3">
<i class="fas ${
type === 'success' ? 'fa-check-circle' :
type === 'error' ? 'fa-exclamation-circle' :
'fa-info-circle'
}"></i>
<span>${message}</span>
<button onclick="this.parentElement.parentElement.remove()" class="ml-2 hover:bg-white/20 rounded p-1">
<i class="fas fa-times"></i>
</button>
</div>
`;
document.body.appendChild(notification);
// Animate in
setTimeout(() => {
notification.classList.remove('translate-x-full');
notification.classList.add('translate-x-0');
}, 100);
// Auto remove after 5 seconds
setTimeout(() => {
notification.classList.add('translate-x-full');
setTimeout(() => notification.remove(), 300);
}, 5000);
}
// Quick custom game functions (same as main custom game functions)
function showQuickCustomGameInput() {
console.log('showQuickCustomGameInput called');
const quickCustomGameInput = document.getElementById('quickCustomGameInput');
const quickCustomGameName = document.getElementById('quickCustomGameName');
if (!quickCustomGameInput) {
console.error('quickCustomGameInput element not found');
alert('Error: Quick custom game input section not found. Please refresh the page and try again.');
return;
}
if (!quickCustomGameName) {
console.error('quickCustomGameName element not found');
alert('Error: Quick custom game name input not found. Please refresh the page and try again.');
return;
}
// Show the input section
quickCustomGameInput.classList.remove('hidden');
// Clear any previous input
quickCustomGameName.value = '';
// Focus on the input with a small delay to ensure visibility
setTimeout(() => {
quickCustomGameName.focus();
quickCustomGameName.select();
}, 150);
console.log('Quick custom game input shown and focused');
}
function hideQuickCustomGameInput() {
console.log('hideQuickCustomGameInput called');
const quickCustomGameInput = document.getElementById('quickCustomGameInput');
const quickCustomGameName = document.getElementById('quickCustomGameName');
if (quickCustomGameInput) {
quickCustomGameInput.classList.add('hidden');
console.log('Quick custom game input hidden');
}
if (quickCustomGameName) {
quickCustomGameName.value = '';
console.log('Quick custom game name input cleared');
}
}
async function createQuickCustomGame() {
console.log('createQuickCustomGame called');
const quickCustomGameNameInput = document.getElementById('quickCustomGameName');
if (!quickCustomGameNameInput) {
console.error('Quick custom game name input not found');
alert('Error: Quick custom game input field not found. Please refresh the page and try again.');
return;
}
const customGameName = quickCustomGameNameInput.value.trim();
console.log('Quick custom game name:', customGameName);
if (!customGameName) {
alert('Please enter a game name');
quickCustomGameNameInput.focus();
return;
}
// Validate game name length
if (customGameName.length < 2) {
alert('Game name must be at least 2 characters long');
quickCustomGameNameInput.focus();
return;
}
if (customGameName.length > 50) {
alert('Game name must be less than 50 characters');
quickCustomGameNameInput.focus();
return;
}
try {
// Generate random styling
const gameStyle = getRandomGameStyle(customGameName);
// Call backend API to store custom game
const response = await fetch('/custom-games', {
method: 'POST',
headers: {
'X-CSRF-TOKEN': document.querySelector('meta[name="csrf-token"]')?.getAttribute('content') || '',
'Content-Type': 'application/json',
'Accept': 'application/json'
},
body: JSON.stringify({
name: customGameName,
icon: gameStyle.icon,
color_gradient: gameStyle.gradient
})
});
const result = await response.json();
if (result.success) {
// Add the custom game to the select dropdown
const gameSelect = document.getElementById('productGame');
if (gameSelect) {
let customOptgroup = gameSelect.querySelector('optgroup[label="Custom Games"]');
// Create optgroup if it doesn't exist
if (!customOptgroup) {
customOptgroup = document.createElement('optgroup');
customOptgroup.label = 'Custom Games';
customOptgroup.id = 'customGamesOptgroup';
gameSelect.appendChild(customOptgroup);
console.log('Created new Custom Games optgroup');
}
// Add new option
const newOption = document.createElement('option');
newOption.value = customGameName;
newOption.textContent = customGameName;
customOptgroup.appendChild(newOption);
console.log('Added new quick custom game option:', customGameName);
}
// Real-time update: Add the new custom game card to the modal
addCustomGameCardToModal(result.data);
// Hide the quick custom game input
hideQuickCustomGameInput();
// Show success popup
showCustomGameSuccessPopup(customGameName);
// Show success notification
showNotification(result.message, 'success');
} else {
showNotification(result.message, 'error');
quickCustomGameNameInput.focus();
}
} catch (error) {
console.error('Error creating custom game:', error);
showNotification('Failed to create custom game. Please try again.', 'error');
quickCustomGameNameInput.focus();
}
}
// Random color and icon generators for custom games
const customGameColors = [
'from-red-500 to-pink-500',
'from-orange-500 to-red-500',
'from-yellow-500 to-orange-500',
'from-green-500 to-teal-500',
'from-teal-500 to-cyan-500',
'from-blue-500 to-indigo-500',
'from-indigo-500 to-purple-500',
'from-purple-500 to-pink-500',
'from-pink-500 to-rose-500',
'from-emerald-500 to-green-500',
'from-cyan-500 to-blue-500',
'from-violet-500 to-purple-500'
];
const customGameIcons = [
'fas fa-gamepad',
'fas fa-dice',
'fas fa-chess',
'fas fa-puzzle-piece',
'fas fa-trophy',
'fas fa-crown',
'fas fa-gem',
'fas fa-fire',
'fas fa-bolt',
'fas fa-magic',
'fas fa-dragon',
'fas fa-shield',
'fas fa-sword',
'fas fa-heart',
'fas fa-star',
'fas fa-moon',
'fas fa-sun',
'fas fa-leaf',
'fas fa-snowflake',
'fas fa-mountain'
];
// Generate random styling for custom game
function getRandomGameStyle(gameName) {
// Use game name as seed for consistent colors
let hash = 0;
for (let i = 0; i < gameName.length; i++) {
hash = ((hash << 5) - hash + gameName.charCodeAt(i)) & 0xffffffff;
}
const colorIndex = Math.abs(hash) % customGameColors.length;
const iconIndex = Math.abs(hash >> 8) % customGameIcons.length;
return {
gradient: customGameColors[colorIndex],
icon: customGameIcons[iconIndex]
};
}
// Create custom game category
async function createCustomGame() {
console.log('createCustomGame called');
const customGameNameInput = document.getElementById('customGameName');
if (!customGameNameInput) {
console.error('Custom game name input not found');
alert('Error: Custom game input field not found. Please refresh the page and try again.');
return;
}
const customGameName = customGameNameInput.value.trim();
console.log('Custom game name:', customGameName);
if (!customGameName) {
alert('Please enter a game name');
customGameNameInput.focus();
return;
}
// Validate game name length
if (customGameName.length < 2) {
alert('Game name must be at least 2 characters long');
customGameNameInput.focus();
return;
}
if (customGameName.length > 50) {
alert('Game name must be less than 50 characters');
customGameNameInput.focus();
return;
}
try {
// Generate random styling
const gameStyle = getRandomGameStyle(customGameName);
// Call backend API to store custom game
const response = await fetch('/custom-games', {
method: 'POST',
headers: {
'X-CSRF-TOKEN': document.querySelector('meta[name="csrf-token"]')?.getAttribute('content') || '',
'Content-Type': 'application/json',
'Accept': 'application/json'
},
body: JSON.stringify({
name: customGameName,
icon: gameStyle.icon,
color_gradient: gameStyle.gradient
})
});
const result = await response.json();
if (result.success) {
// Add the custom game to the select dropdown
const gameSelect = document.getElementById('productGame');
if (gameSelect) {
let customOptgroup = gameSelect.querySelector('optgroup[label="Custom Games"]');
// Create optgroup if it doesn't exist
if (!customOptgroup) {
customOptgroup = document.createElement('optgroup');
customOptgroup.label = 'Custom Games';
customOptgroup.id = 'customGamesOptgroup';
gameSelect.appendChild(customOptgroup);
console.log('Created new Custom Games optgroup');
}
// Add new option
const newOption = document.createElement('option');
newOption.value = customGameName;
newOption.textContent = customGameName;
customOptgroup.appendChild(newOption);
console.log('Added new custom game option:', customGameName);
}
// Real-time update: Add the new custom game card to the modal
addCustomGameCardToModal(result.data);
// Hide the custom game input
hideCustomGameInput();
// Show success popup
showCustomGameSuccessPopup(customGameName);
// Show success notification
showNotification(result.message, 'success');
} else {
showNotification(result.message, 'error');
customGameNameInput.focus();
}
} catch (error) {
console.error('Error creating custom game:', error);
showNotification('Failed to create custom game. Please try again.', 'error');
customGameNameInput.focus();
}
}
// Real-time function to add custom game card to modal
function addCustomGameCardToModal(customGameData) {
const otherGamesModal = document.getElementById('otherGamesModal');
if (!otherGamesModal) return;
const gameGrid = otherGamesModal.querySelector('.grid');
if (!gameGrid) return;
// Extract color from gradient
const gradientParts = customGameData.color_gradient.split(' ');
const primaryColor = gradientParts[0].replace('from-', '').replace('-500', '');
// Map to color classes
const colorMap = {
'red': ['from-red-500/20 to-pink-500/20', 'border-red-500/30', 'hover:border-red-500/50'],
'pink': ['from-pink-500/20 to-rose-500/20', 'border-pink-500/30', 'hover:border-pink-500/50'],
'rose': ['from-rose-500/20 to-pink-500/20', 'border-rose-500/30', 'hover:border-rose-500/50'],
'purple': ['from-purple-500/20 to-blue-500/20', 'border-purple-500/30', 'hover:border-purple-500/50'],
'blue': ['from-blue-500/20 to-indigo-500/20', 'border-blue-500/30', 'hover:border-blue-500/50'],
'green': ['from-green-500/20 to-teal-500/20', 'border-green-500/30', 'hover:border-green-500/50'],
'orange': ['from-orange-500/20 to-red-500/20', 'border-orange-500/30', 'hover:border-orange-500/50'],
'yellow': ['from-yellow-500/20 to-orange-500/20', 'border-yellow-500/30', 'hover:border-yellow-500/50'],
'teal': ['from-teal-500/20 to-cyan-500/20', 'border-teal-500/30', 'hover:border-teal-500/50'],
'cyan': ['from-cyan-500/20 to-blue-500/20', 'border-cyan-500/30', 'hover:border-cyan-500/50'],
'indigo': ['from-indigo-500/20 to-purple-500/20', 'border-indigo-500/30', 'hover:border-indigo-500/50'],
'violet': ['from-violet-500/20 to-purple-500/20', 'border-violet-500/30', 'hover:border-violet-500/50'],
'emerald': ['from-emerald-500/20 to-green-500/20', 'border-emerald-500/30', 'hover:border-emerald-500/50']
};
const colors = colorMap[primaryColor] || colorMap['purple'];
// Create the new card element
const newCard = document.createElement('div');
newCard.className = 'relative custom-game-card';
newCard.innerHTML = `
<button onclick="openNewProductModal('${customGameData.name}')" class="w-full p-6 bg-gradient-to-r ${colors[0]} border ${colors[1]} rounded-xl text-left ${colors[2]} transition-all duration-300 group">
<div class="flex flex-col items-center text-center">
<div class="w-12 h-12 bg-gradient-to-r ${customGameData.color_gradient} rounded-lg flex items-center justify-center mb-3 group-hover:scale-110 transition-transform duration-300">
<i class="${customGameData.icon} text-white text-xl"></i>
</div>
<div class="text-white font-bold text-lg mb-1">${customGameData.name}</div>
<div class="${colors[0].includes('purple') ? 'text-purple-300' : 'text-' + primaryColor + '-300'} text-sm">Custom game</div>
</div>
</button>
<button onclick="deleteCustomGame('${customGameData.name}')" class="delete-btn absolute -top-2 -right-2 w-8 h-8 bg-red-500 hover:bg-red-600 text-white rounded-full flex items-center justify-center opacity-0 invisible transition-all duration-300 transform scale-0 z-10 shadow-lg">
<i class="fas fa-minus text-sm"></i>
</button>
`;
// Find the delete button (last item) and insert before it
const deleteButton = gameGrid.querySelector('button[onclick*="showDeleteCustomGameInput"]');
if (deleteButton && deleteButton.parentElement) {
gameGrid.insertBefore(newCard, deleteButton.parentElement);
} else {
gameGrid.appendChild(newCard);
}
// Add animation
newCard.style.opacity = '0';
newCard.style.transform = 'scale(0.8)';
setTimeout(() => {
newCard.style.transition = 'all 0.3s ease';
newCard.style.opacity = '1';
newCard.style.transform = 'scale(1)';
}, 100);
}
// Show custom game success popup
function showCustomGameSuccessPopup(gameName) {
console.log('showCustomGameSuccessPopup called with:', gameName); // Debug log
const successNameElement = document.getElementById('customGameSuccessName');
const gameNameButtonElement = document.getElementById('gameNameInButton');
const successModal = document.getElementById('customGameSuccessModal');
const addItemButton = document.getElementById('addItemForGame');
if (successNameElement && gameNameButtonElement && successModal && addItemButton) {
successNameElement.textContent = gameName;
gameNameButtonElement.textContent = gameName;
// Set up the "Add Item" button click handler
addItemButton.onclick = function() {
closeCustomGameSuccessModal();
openNewProductModal(gameName);
};
successModal.classList.remove('hidden');
successModal.classList.add('flex');
console.log('Success popup shown for game:', gameName); // Debug log
} else {
console.error('Success popup elements not found:'); // Debug log
console.log('successNameElement:', successNameElement);
console.log('gameNameButtonElement:', gameNameButtonElement);
console.log('successModal:', successModal);
console.log('addItemButton:', addItemButton);
// Fallback alert if modal elements are missing
alert(`Custom game "${gameName}" has been added successfully!`);
}
}
// Close custom game success modal
function closeCustomGameSuccessModal() {
document.getElementById('customGameSuccessModal').classList.add('hidden');
document.getElementById('customGameSuccessModal').classList.remove('flex');
}
// Show add more category (go back to category modal)
function showAddMoreCategory() {
closeCustomGameSuccessModal();
document.getElementById('categoryModal').classList.remove('hidden');
document.getElementById('categoryModal').classList.add('flex');
}
// Handle Enter key in custom game input
document.addEventListener('DOMContentLoaded', function() {
const customGameInput = document.getElementById('customGameName');
if (customGameInput) {
customGameInput.addEventListener('keypress', function(e) {
if (e.key === 'Enter') {
createCustomGame();
}
});
}
});
// Open new product modal with pre-selected category
function openNewProductModal(gameCategory) {
// Close both modals
closeCategoryModal();
closeOtherGamesModal();
// Reset form for new product
document.getElementById('productForm').reset();
document.getElementById('currentImagePreview').classList.add('hidden');
document.getElementById('productImage').setAttribute('required', 'required');
// Set the selected game category
document.getElementById('productGame').value = gameCategory;
// Set default values for specifications
document.getElementById('productType').value = 'Digital Account';
document.getElementById('productPlatform').value = 'Multi-Platform';
document.getElementById('productRegion').value = 'Global';
document.getElementById('deliveryMethod').value = 'Instant Digital';
document.getElementById('productWarranty').value = 'Lifetime Support';
document.getElementById('supportLevel').value = '24/7 Available';
// Update modal title based on category
let modalTitle = 'Add New Product';
if (gameCategory === 'Genshin') {
modalTitle = 'Add Genshin Impact Product';
} else if (gameCategory === 'Starrail') {
modalTitle = 'Add Honkai: Star Rail Product';
} else if (gameCategory === 'WutheringWave') {
modalTitle = 'Add Wuthering Waves Product';
} else if (gameCategory === 'ZenlessZoneZero') {
modalTitle = 'Add Zenless Zone Zero Product';
} else if (gameCategory === 'Arknights') {
modalTitle = 'Add Arknights Product';
} else if (gameCategory === 'AzurLane') {
modalTitle = 'Add Azur Lane Product';
} else {
modalTitle = `Add ${gameCategory} Product`;
}
openModal(modalTitle);
}
// Close modal when clicking outside
document.getElementById('productModal').addEventListener('click', (e) => {
if (e.target === e.currentTarget) {
closeModal();
}
});
// Close success modal when clicking outside
document.getElementById('customGameSuccessModal').addEventListener('click', (e) => {
if (e.target === e.currentTarget) {
closeCustomGameSuccessModal();
}
});
// File upload functionality
document.addEventListener('DOMContentLoaded', function() {
const fileInput = document.getElementById('productImage');
const uploadArea = document.getElementById('fileUploadArea');
const uploadContent = document.getElementById('uploadContent');
const fileInfo = document.getElementById('fileInfo');
const fileName = document.getElementById('fileName');
const fileSize = document.getElementById('fileSize');
const removeBtn = document.getElementById('removeFile');
// Handle file input change
fileInput.addEventListener('change', function(e) {
const file = e.target.files[0];
if (file) {
handleFile(file);
} else {
resetFileDisplay();
}
});
// Handle drag and drop
uploadArea.addEventListener('dragover', function(e) {
e.preventDefault();
uploadArea.classList.add('dragover');
});
uploadArea.addEventListener('dragleave', function(e) {
e.preventDefault();
uploadArea.classList.remove('dragover');
});
uploadArea.addEventListener('drop', function(e) {
e.preventDefault();
uploadArea.classList.remove('dragover');
const files = e.dataTransfer.files;
if (files.length > 0) {
const file = files[0];
if (file.type.startsWith('image/')) {
fileInput.files = files;
handleFile(file);
}
}
});
// Handle remove file
removeBtn.addEventListener('click', function(e) {
e.stopPropagation();
fileInput.value = '';
resetFileDisplay();
});
function handleFile(file) {
// Validate file size (10MB)
if (file.size > 10 * 1024 * 1024) {
alert('File size must be less than 10MB');
fileInput.value = '';
return;
}
// Validate file type
if (!file.type.startsWith('image/')) {
alert('Please select an image file');
fileInput.value = '';
return;
}
// Show file info
fileName.textContent = file.name;
fileSize.textContent = formatFileSize(file.size);
uploadContent.classList.add('hidden');
fileInfo.classList.remove('hidden');
}
function resetFileDisplay() {
uploadContent.classList.remove('hidden');
fileInfo.classList.add('hidden');
fileName.textContent = '';
fileSize.textContent = '';
}
function formatFileSize(bytes) {
if (bytes === 0) return '0 Bytes';
const k = 1024;
const sizes = ['Bytes', 'KB', 'MB', 'GB'];
const i = Math.floor(Math.log(bytes) / Math.log(k));
return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];
}
});
</script>
</x-app-layout>