170 lines
9.1 KiB
Vue
170 lines
9.1 KiB
Vue
<script setup lang="ts">
|
|
import { Head, Link, router } from '@inertiajs/vue3';
|
|
import { Gift, Plus, Search, Filter, Edit2, Trash2, Eye, EyeOff, AlertTriangle, X } from 'lucide-vue-next';
|
|
import { ref } from 'vue';
|
|
|
|
interface Bonus {
|
|
id: number;
|
|
name: string;
|
|
description: string;
|
|
is_active: boolean;
|
|
order: number;
|
|
brand_color: string;
|
|
}
|
|
|
|
defineProps<{
|
|
bonuses: Bonus[];
|
|
}>();
|
|
|
|
const isDeleteModalOpen = ref(false);
|
|
const bonusToDelete = ref<Bonus | null>(null);
|
|
|
|
const confirmDelete = (bonus: Bonus) => {
|
|
bonusToDelete.value = bonus;
|
|
isDeleteModalOpen.value = true;
|
|
};
|
|
|
|
const deleteBonus = () => {
|
|
if (bonusToDelete.value) {
|
|
router.delete(`/admin/bonuses/${bonusToDelete.value.id}`, {
|
|
onSuccess: () => {
|
|
isDeleteModalOpen.value = false;
|
|
bonusToDelete.value = null;
|
|
},
|
|
});
|
|
}
|
|
};
|
|
</script>
|
|
|
|
<template>
|
|
<Head title="Manage Bonuses" />
|
|
|
|
<div class="relative">
|
|
<!-- Delete Confirmation Modal -->
|
|
<Transition
|
|
enter-active-class="transition duration-300 ease-out"
|
|
enter-from-class="opacity-0 scale-95"
|
|
enter-to-class="opacity-100 scale-100"
|
|
leave-active-class="transition duration-200 ease-in"
|
|
leave-from-class="opacity-100 scale-100"
|
|
leave-to-class="opacity-0 scale-95"
|
|
>
|
|
<div v-if="isDeleteModalOpen" class="fixed inset-0 z-[100] flex items-center justify-center p-4">
|
|
<div class="absolute inset-0 bg-black/80 backdrop-blur-sm" @click="isDeleteModalOpen = false"></div>
|
|
<div class="relative bg-[#0f172a] border border-white/10 rounded-[32px] p-10 max-w-md w-full shadow-2xl shadow-black/50">
|
|
<button @click="isDeleteModalOpen = false" class="absolute top-6 right-6 text-gray-500 hover:text-white transition">
|
|
<X :size="24" />
|
|
</button>
|
|
|
|
<div class="w-20 h-20 bg-red-500/10 rounded-full flex items-center justify-center mx-auto mb-8 text-red-500">
|
|
<AlertTriangle :size="40" />
|
|
</div>
|
|
|
|
<h2 class="text-2xl font-black italic uppercase text-center mb-4 tracking-tight">Wait a <span class="text-red-500">second</span></h2>
|
|
<p class="text-gray-400 text-center mb-10 leading-relaxed">Are you sure you want to delete <span class="text-white font-bold">{{ bonusToDelete?.name }}</span>? This action cannot be undone.</p>
|
|
|
|
<div class="grid grid-cols-2 gap-4">
|
|
<button @click="isDeleteModalOpen = false" class="py-4 rounded-2xl bg-white/5 hover:bg-white/10 text-white font-black uppercase tracking-widest text-[10px] transition">Cancel</button>
|
|
<button @click="deleteBonus" class="py-4 rounded-2xl bg-red-600 hover:bg-red-700 text-white font-black uppercase tracking-widest text-[10px] transition shadow-lg shadow-red-600/20">Delete Bonus</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</Transition>
|
|
|
|
<div class="space-y-8">
|
|
<!-- Header Section -->
|
|
<div class="flex flex-col md:flex-row md:items-center justify-between gap-6 bg-[#0f172a] p-8 rounded-[32px] border border-white/5 shadow-xl">
|
|
<div>
|
|
<h1 class="text-3xl font-black italic tracking-tighter uppercase mb-2">Bonus <span class="text-purple-500">Inventory</span></h1>
|
|
<p class="text-gray-400 text-sm font-medium">Manage and organize your casino deals effortlessly.</p>
|
|
</div>
|
|
<Link
|
|
href="/admin/bonuses/create"
|
|
class="bg-gradient-to-r from-purple-600 to-blue-600 hover:scale-105 transition-all duration-300 text-white px-8 py-4 rounded-2xl font-black uppercase tracking-widest text-xs flex items-center gap-3 shadow-lg shadow-purple-500/20"
|
|
>
|
|
<Plus :size="18" /> Add New Bonus
|
|
</Link>
|
|
</div>
|
|
|
|
<!-- Filters & Search -->
|
|
<div class="flex items-center gap-4">
|
|
<div class="relative flex-1">
|
|
<Search class="absolute left-4 top-1/2 -translate-y-1/2 text-gray-500" :size="18" />
|
|
<input type="text" placeholder="Search bonuses..." class="w-full bg-[#0f172a] border border-white/5 rounded-2xl py-4 pl-12 pr-4 outline-none focus:border-purple-500/50 transition text-sm">
|
|
</div>
|
|
<button class="bg-[#0f172a] border border-white/5 p-4 rounded-2xl hover:bg-white/5 transition text-gray-400">
|
|
<Filter :size="18" />
|
|
</button>
|
|
</div>
|
|
|
|
<!-- Bonus Grid -->
|
|
<div class="grid grid-cols-1 md:grid-cols-2 xl:grid-cols-3 gap-6">
|
|
<div
|
|
v-for="bonus in bonuses"
|
|
:key="bonus.id"
|
|
class="group bg-[#0f172a] rounded-[32px] border border-white/5 overflow-hidden hover:border-purple-500/30 transition-all duration-500 shadow-lg hover:shadow-2xl hover:shadow-purple-500/10 flex flex-col"
|
|
>
|
|
<!-- Top Section -->
|
|
<div class="p-8 flex-1">
|
|
<div class="flex justify-between items-start mb-6">
|
|
<div
|
|
class="w-12 h-12 rounded-2xl flex items-center justify-center font-black italic shadow-inner border border-white/5"
|
|
:style="{ backgroundColor: bonus.brand_color + '20', color: bonus.brand_color }"
|
|
>
|
|
{{ bonus.name.charAt(0) }}
|
|
</div>
|
|
<div class="flex gap-2">
|
|
<span
|
|
:class="[
|
|
'px-3 py-1 rounded-full text-[10px] font-black uppercase tracking-widest border',
|
|
bonus.is_active
|
|
? 'bg-green-500/10 text-green-400 border-green-500/20'
|
|
: 'bg-red-500/10 text-red-400 border-red-500/20'
|
|
]"
|
|
>
|
|
{{ bonus.is_active ? 'Active' : 'Inactive' }}
|
|
</span>
|
|
</div>
|
|
</div>
|
|
|
|
<h3 class="text-xl font-black italic tracking-tight uppercase mb-2 group-hover:text-purple-400 transition">{{ bonus.name }}</h3>
|
|
<p class="text-gray-500 text-sm leading-relaxed line-clamp-2 mb-6">{{ bonus.description || 'No description provided.' }}</p>
|
|
|
|
<div class="flex items-center gap-4 text-[10px] font-bold text-gray-400 uppercase tracking-widest border-t border-white/5 pt-6">
|
|
<span class="flex items-center gap-2"><i class="fas fa-sort"></i> Order: {{ bonus.order }}</span>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Action Bar -->
|
|
<div class="p-4 bg-white/[0.02] border-t border-white/5 grid grid-cols-2 gap-2">
|
|
<Link
|
|
:href="`/admin/bonuses/${bonus.id}/edit`"
|
|
class="flex items-center justify-center gap-2 py-3 rounded-xl bg-white/5 hover:bg-blue-500/20 hover:text-blue-400 transition-all text-xs font-bold uppercase tracking-widest"
|
|
>
|
|
<Edit2 :size="14" /> Edit
|
|
</Link>
|
|
<button
|
|
@click="confirmDelete(bonus)"
|
|
class="flex items-center justify-center gap-2 py-3 rounded-xl bg-white/5 hover:bg-red-500/20 hover:text-red-400 transition-all text-xs font-bold uppercase tracking-widest"
|
|
>
|
|
<Trash2 :size="14" /> Delete
|
|
</button>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Empty State -->
|
|
<div v-if="bonuses.length === 0" class="col-span-full bg-[#0f172a] border-2 border-dashed border-white/5 rounded-[32px] p-20 text-center">
|
|
<div class="w-20 h-20 bg-white/5 rounded-full flex items-center justify-center mx-auto mb-6">
|
|
<Gift :size="32" class="text-gray-500" />
|
|
</div>
|
|
<h3 class="text-2xl font-black italic uppercase mb-2">No Bonuses Found</h3>
|
|
<p class="text-gray-500 mb-8 max-w-xs mx-auto text-sm">Your inventory is currently empty. Start by adding a new casino deal.</p>
|
|
<Link href="/admin/bonuses/create" class="inline-flex items-center gap-3 bg-white text-black px-8 py-4 rounded-2xl font-black uppercase tracking-widest text-xs hover:bg-purple-500 hover:text-white transition-all shadow-xl">
|
|
<Plus :size="18" /> Create One Now
|
|
</Link>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</template>
|