Files
bratanbonus/resources/js/pages/Admin/Bonuses/Index.vue
T
Dolo c178fab470
linter / quality (push) Has been cancelled
tests / ci (8.3) (push) Has been cancelled
tests / ci (8.4) (push) Has been cancelled
tests / ci (8.5) (push) Has been cancelled
initial commit
2026-04-09 19:53:31 +02:00

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>