Fix: app.blade, .gitignore und JS-Verzeichnisse hinzugefügt
This commit is contained in:
+3
-3
@@ -6,9 +6,9 @@
|
|||||||
/public/storage
|
/public/storage
|
||||||
/storage/*.key
|
/storage/*.key
|
||||||
/storage/pail
|
/storage/pail
|
||||||
/resources/js/actions
|
#/resources/js/actions
|
||||||
/resources/js/routes
|
#/resources/js/routes
|
||||||
/resources/js/wayfinder
|
#/resources/js/wayfinder
|
||||||
/vendor
|
/vendor
|
||||||
.DS_Store
|
.DS_Store
|
||||||
.env
|
.env
|
||||||
|
|||||||
@@ -1,8 +1,17 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { Head, useForm, Link } from '@inertiajs/vue3';
|
import { Head, useForm, Link } from '@inertiajs/vue3';
|
||||||
import type { BreadcrumbItem } from '@/types';
|
import {
|
||||||
|
Plus,
|
||||||
|
Trash2,
|
||||||
|
Link as LinkIcon,
|
||||||
|
DollarSign,
|
||||||
|
RotateCw,
|
||||||
|
Award,
|
||||||
|
XSquare,
|
||||||
|
Star,
|
||||||
|
ArrowLeft,
|
||||||
|
} from 'lucide-vue-next';
|
||||||
import { ref, watch } from 'vue';
|
import { ref, watch } from 'vue';
|
||||||
import { Plus, Trash2, Image as ImageIcon, Link as LinkIcon, Palette, Droplet, DollarSign, Percent, RotateCw, Award, CheckSquare, XSquare, Star, ArrowLeft } from 'lucide-vue-next';
|
|
||||||
|
|
||||||
interface PredefinedBadge {
|
interface PredefinedBadge {
|
||||||
label: string;
|
label: string;
|
||||||
@@ -14,12 +23,6 @@ const props = defineProps<{
|
|||||||
predefinedKeyFeatures: string[];
|
predefinedKeyFeatures: string[];
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
const breadcrumbs: BreadcrumbItem[] = [
|
|
||||||
{ title: 'Dashboard', href: '/dashboard' },
|
|
||||||
{ title: 'Bonuses', href: '/admin/bonuses' },
|
|
||||||
{ title: 'Create', href: '/admin/bonuses/create' },
|
|
||||||
];
|
|
||||||
|
|
||||||
const form = useForm({
|
const form = useForm({
|
||||||
name: '',
|
name: '',
|
||||||
description: '',
|
description: '',
|
||||||
@@ -43,7 +46,10 @@ const form = useForm({
|
|||||||
const newBadge = ref('');
|
const newBadge = ref('');
|
||||||
const addBadge = () => {
|
const addBadge = () => {
|
||||||
if (newBadge.value.trim()) {
|
if (newBadge.value.trim()) {
|
||||||
form.badges.push({ label: newBadge.value.trim(), class: 'bg-white/10' });
|
form.badges.push({
|
||||||
|
label: newBadge.value.trim(),
|
||||||
|
class: 'bg-white/10',
|
||||||
|
});
|
||||||
newBadge.value = '';
|
newBadge.value = '';
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -53,7 +59,7 @@ const removeBadge = (index: number) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const addPredefinedBadge = (badge: PredefinedBadge) => {
|
const addPredefinedBadge = (badge: PredefinedBadge) => {
|
||||||
if (!form.badges.some(b => b.label === badge.label)) {
|
if (!form.badges.some((b) => b.label === badge.label)) {
|
||||||
form.badges.push(badge);
|
form.badges.push(badge);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -91,13 +97,16 @@ const handleImageFileChange = (e: Event) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Watch for changes in image_path to update preview if it's a URL
|
// Watch for changes in image_path to update preview if it's a URL
|
||||||
watch(() => form.image_path, (newPath) => {
|
watch(
|
||||||
if (newPath && !form.image_file) {
|
() => form.image_path,
|
||||||
imagePreviewUrl.value = newPath;
|
(newPath) => {
|
||||||
} else if (!newPath && !form.image_file) {
|
if (newPath && !form.image_file) {
|
||||||
imagePreviewUrl.value = null;
|
imagePreviewUrl.value = newPath;
|
||||||
}
|
} else if (!newPath && !form.image_file) {
|
||||||
});
|
imagePreviewUrl.value = null;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
const submit = () => {
|
const submit = () => {
|
||||||
form.post('/admin/bonuses', {
|
form.post('/admin/bonuses', {
|
||||||
@@ -107,7 +116,7 @@ const submit = () => {
|
|||||||
onError: (errors) => {
|
onError: (errors) => {
|
||||||
console.error(errors);
|
console.error(errors);
|
||||||
// You might want to show a generic error notification here
|
// You might want to show a generic error notification here
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
@@ -117,73 +126,157 @@ const submit = () => {
|
|||||||
|
|
||||||
<div class="space-y-8">
|
<div class="space-y-8">
|
||||||
<!-- Header Section -->
|
<!-- Header Section -->
|
||||||
<div class="flex items-center justify-between gap-6 bg-[#0f172a] p-8 rounded-[32px] border border-white/5 shadow-xl">
|
<div
|
||||||
|
class="flex items-center justify-between gap-6 rounded-[32px] border border-white/5 bg-[#0f172a] p-8 shadow-xl"
|
||||||
|
>
|
||||||
<div class="flex items-center gap-4">
|
<div class="flex items-center gap-4">
|
||||||
<Link href="/admin/bonuses" class="w-10 h-10 rounded-xl bg-white/5 flex items-center justify-center text-gray-400 hover:text-white hover:bg-white/10 transition">
|
<Link
|
||||||
|
href="/admin/bonuses"
|
||||||
|
class="flex h-10 w-10 items-center justify-center rounded-xl bg-white/5 text-gray-400 transition hover:bg-white/10 hover:text-white"
|
||||||
|
>
|
||||||
<ArrowLeft :size="20" />
|
<ArrowLeft :size="20" />
|
||||||
</Link>
|
</Link>
|
||||||
<h1 class="text-3xl font-black italic tracking-tighter uppercase">Create New <span class="text-purple-500">Bonus</span></h1>
|
<h1
|
||||||
|
class="text-3xl font-black tracking-tighter uppercase italic"
|
||||||
|
>
|
||||||
|
Create New <span class="text-purple-500">Bonus</span>
|
||||||
|
</h1>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<form @submit.prevent="submit" class="bg-[#0f172a] rounded-[32px] border border-white/5 shadow-xl p-8 space-y-10">
|
<form
|
||||||
<div class="grid grid-cols-1 lg:grid-cols-2 gap-12">
|
@submit.prevent="submit"
|
||||||
|
class="space-y-10 rounded-[32px] border border-white/5 bg-[#0f172a] p-8 shadow-xl"
|
||||||
|
>
|
||||||
|
<div class="grid grid-cols-1 gap-12 lg:grid-cols-2">
|
||||||
<!-- Left Column: Content -->
|
<!-- Left Column: Content -->
|
||||||
<div class="space-y-8">
|
<div class="space-y-8">
|
||||||
<section class="space-y-6">
|
<section class="space-y-6">
|
||||||
<h2 class="text-xl font-black italic uppercase tracking-tight text-blue-400 flex items-center gap-3">
|
<h2
|
||||||
<span class="w-8 h-[2px] bg-blue-400"></span> Main Info
|
class="flex items-center gap-3 text-xl font-black tracking-tight text-blue-400 uppercase italic"
|
||||||
|
>
|
||||||
|
<span class="h-[2px] w-8 bg-blue-400"></span> Main
|
||||||
|
Info
|
||||||
</h2>
|
</h2>
|
||||||
|
|
||||||
<div class="space-y-4">
|
<div class="space-y-4">
|
||||||
<label class="block">
|
<label class="block">
|
||||||
<span class="text-gray-500 font-black uppercase text-[10px] tracking-[0.2em] mb-2 block">Casino Name</span>
|
<span
|
||||||
<input v-model="form.name" type="text" class="form-input" required placeholder="e.g. STAKE.COM">
|
class="mb-2 block text-[10px] font-black tracking-[0.2em] text-gray-500 uppercase"
|
||||||
|
>Casino Name</span
|
||||||
|
>
|
||||||
|
<input
|
||||||
|
v-model="form.name"
|
||||||
|
type="text"
|
||||||
|
class="form-input"
|
||||||
|
required
|
||||||
|
placeholder="e.g. STAKE.COM"
|
||||||
|
/>
|
||||||
</label>
|
</label>
|
||||||
|
|
||||||
<label class="block">
|
<label class="block">
|
||||||
<span class="text-gray-500 font-black uppercase text-[10px] tracking-[0.2em] mb-2 block">Description / Bonus Text</span>
|
<span
|
||||||
<textarea v-model="form.description" class="form-textarea" rows="4" placeholder="Exklusiver 200% Bonus bis zu 1000€..."></textarea>
|
class="mb-2 block text-[10px] font-black tracking-[0.2em] text-gray-500 uppercase"
|
||||||
|
>Description / Bonus Text</span
|
||||||
|
>
|
||||||
|
<textarea
|
||||||
|
v-model="form.description"
|
||||||
|
class="form-textarea"
|
||||||
|
rows="4"
|
||||||
|
placeholder="Exklusiver 200% Bonus bis zu 1000€..."
|
||||||
|
></textarea>
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<section class="space-y-6">
|
<section class="space-y-6">
|
||||||
<h2 class="text-xl font-black italic uppercase tracking-tight text-purple-400 flex items-center gap-3">
|
<h2
|
||||||
<span class="w-8 h-[2px] bg-purple-400"></span> Visuals & Branding
|
class="flex items-center gap-3 text-xl font-black tracking-tight text-purple-400 uppercase italic"
|
||||||
|
>
|
||||||
|
<span class="h-[2px] w-8 bg-purple-400"></span>
|
||||||
|
Visuals & Branding
|
||||||
</h2>
|
</h2>
|
||||||
|
|
||||||
<div class="grid grid-cols-1 sm:grid-cols-2 gap-6">
|
<div class="grid grid-cols-1 gap-6 sm:grid-cols-2">
|
||||||
<label class="block">
|
<label class="block">
|
||||||
<span class="text-gray-500 font-black uppercase text-[10px] tracking-[0.2em] mb-2 block">Brand Primary Color</span>
|
<span
|
||||||
|
class="mb-2 block text-[10px] font-black tracking-[0.2em] text-gray-500 uppercase"
|
||||||
|
>Brand Primary Color</span
|
||||||
|
>
|
||||||
<div class="flex gap-3">
|
<div class="flex gap-3">
|
||||||
<input v-model="form.brand_color" type="color" class="form-color-input w-14">
|
<input
|
||||||
<input v-model="form.brand_color" type="text" class="form-input flex-1 font-mono text-xs uppercase" placeholder="#A855F7">
|
v-model="form.brand_color"
|
||||||
|
type="color"
|
||||||
|
class="form-color-input w-14"
|
||||||
|
/>
|
||||||
|
<input
|
||||||
|
v-model="form.brand_color"
|
||||||
|
type="text"
|
||||||
|
class="form-input flex-1 font-mono text-xs uppercase"
|
||||||
|
placeholder="#A855F7"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</label>
|
</label>
|
||||||
|
|
||||||
<label class="block">
|
<label class="block">
|
||||||
<span class="text-gray-500 font-black uppercase text-[10px] tracking-[0.2em] mb-2 block">Hover Glow Color (RGBA)</span>
|
<span
|
||||||
<input v-model="form.hover_color" type="text" class="form-input font-mono text-xs" placeholder="rgba(168, 85, 247, 0.8)">
|
class="mb-2 block text-[10px] font-black tracking-[0.2em] text-gray-500 uppercase"
|
||||||
|
>Hover Glow Color (RGBA)</span
|
||||||
|
>
|
||||||
|
<input
|
||||||
|
v-model="form.hover_color"
|
||||||
|
type="text"
|
||||||
|
class="form-input font-mono text-xs"
|
||||||
|
placeholder="rgba(168, 85, 247, 0.8)"
|
||||||
|
/>
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="grid grid-cols-1 sm:grid-cols-2 gap-6 items-end">
|
<div
|
||||||
|
class="grid grid-cols-1 items-end gap-6 sm:grid-cols-2"
|
||||||
|
>
|
||||||
<label class="block">
|
<label class="block">
|
||||||
<span class="text-gray-500 font-black uppercase text-[10px] tracking-[0.2em] mb-2 block">Background Image URL</span>
|
<span
|
||||||
<input v-model="form.image_path" type="text" class="form-input" :disabled="!!form.image_file">
|
class="mb-2 block text-[10px] font-black tracking-[0.2em] text-gray-500 uppercase"
|
||||||
|
>Background Image URL</span
|
||||||
|
>
|
||||||
|
<input
|
||||||
|
v-model="form.image_path"
|
||||||
|
type="text"
|
||||||
|
class="form-input"
|
||||||
|
:disabled="!!form.image_file"
|
||||||
|
/>
|
||||||
</label>
|
</label>
|
||||||
|
|
||||||
<label class="block">
|
<label class="block">
|
||||||
<span class="text-gray-500 font-black uppercase text-[10px] tracking-[0.2em] mb-2 block">Or Upload New File</span>
|
<span
|
||||||
<input type="file" @change="handleImageFileChange" class="form-file-input" accept="image/*">
|
class="mb-2 block text-[10px] font-black tracking-[0.2em] text-gray-500 uppercase"
|
||||||
|
>Or Upload New File</span
|
||||||
|
>
|
||||||
|
<input
|
||||||
|
type="file"
|
||||||
|
@change="handleImageFileChange"
|
||||||
|
class="form-file-input"
|
||||||
|
accept="image/*"
|
||||||
|
/>
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div v-if="imagePreviewUrl" class="relative group aspect-video rounded-2xl overflow-hidden border border-white/5 bg-black/40">
|
<div
|
||||||
<img :src="imagePreviewUrl" class="w-full h-full object-cover opacity-60" />
|
v-if="imagePreviewUrl"
|
||||||
<div class="absolute inset-0 flex items-center justify-center">
|
class="group relative aspect-video overflow-hidden rounded-2xl border border-white/5 bg-black/40"
|
||||||
<span class="bg-black/60 backdrop-blur-md px-4 py-2 rounded-full text-[10px] font-black uppercase tracking-widest border border-white/10">Image Preview</span>
|
>
|
||||||
|
<img
|
||||||
|
:src="imagePreviewUrl"
|
||||||
|
class="h-full w-full object-cover opacity-60"
|
||||||
|
/>
|
||||||
|
<div
|
||||||
|
class="absolute inset-0 flex items-center justify-center"
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
class="rounded-full border border-white/10 bg-black/60 px-4 py-2 text-[10px] font-black tracking-widest uppercase backdrop-blur-md"
|
||||||
|
>Image Preview</span
|
||||||
|
>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
@@ -192,146 +285,349 @@ const submit = () => {
|
|||||||
<!-- Right Column: Stats & Features -->
|
<!-- Right Column: Stats & Features -->
|
||||||
<div class="space-y-8">
|
<div class="space-y-8">
|
||||||
<section class="space-y-6">
|
<section class="space-y-6">
|
||||||
<h2 class="text-xl font-black italic uppercase tracking-tight text-green-400 flex items-center gap-3">
|
<h2
|
||||||
<span class="w-8 h-[2px] bg-green-400"></span> Bonus Details
|
class="flex items-center gap-3 text-xl font-black tracking-tight text-green-400 uppercase italic"
|
||||||
|
>
|
||||||
|
<span class="h-[2px] w-8 bg-green-400"></span> Bonus
|
||||||
|
Details
|
||||||
</h2>
|
</h2>
|
||||||
|
|
||||||
<div class="grid grid-cols-2 gap-4">
|
<div class="grid grid-cols-2 gap-4">
|
||||||
<label class="block">
|
<label class="block">
|
||||||
<span class="text-gray-500 font-black uppercase text-[10px] tracking-[0.2em] mb-2 block">Min Deposit</span>
|
<span
|
||||||
|
class="mb-2 block text-[10px] font-black tracking-[0.2em] text-gray-500 uppercase"
|
||||||
|
>Min Deposit</span
|
||||||
|
>
|
||||||
<div class="relative">
|
<div class="relative">
|
||||||
<DollarSign class="absolute left-4 top-1/2 -translate-y-1/2 text-gray-600" :size="14" />
|
<DollarSign
|
||||||
<input v-model="form.min_deposit" type="text" class="form-input pl-10" placeholder="20€">
|
class="absolute top-1/2 left-4 -translate-y-1/2 text-gray-600"
|
||||||
|
:size="14"
|
||||||
|
/>
|
||||||
|
<input
|
||||||
|
v-model="form.min_deposit"
|
||||||
|
type="text"
|
||||||
|
class="form-input pl-10"
|
||||||
|
placeholder="20€"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</label>
|
</label>
|
||||||
<label class="block">
|
<label class="block">
|
||||||
<span class="text-gray-500 font-black uppercase text-[10px] tracking-[0.2em] mb-2 block">Max Bet</span>
|
<span
|
||||||
|
class="mb-2 block text-[10px] font-black tracking-[0.2em] text-gray-500 uppercase"
|
||||||
|
>Max Bet</span
|
||||||
|
>
|
||||||
<div class="relative">
|
<div class="relative">
|
||||||
<XSquare class="absolute left-4 top-1/2 -translate-y-1/2 text-gray-600" :size="14" />
|
<XSquare
|
||||||
<input v-model="form.max_bet" type="text" class="form-input pl-10" placeholder="5€">
|
class="absolute top-1/2 left-4 -translate-y-1/2 text-gray-600"
|
||||||
|
:size="14"
|
||||||
|
/>
|
||||||
|
<input
|
||||||
|
v-model="form.max_bet"
|
||||||
|
type="text"
|
||||||
|
class="form-input pl-10"
|
||||||
|
placeholder="5€"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</label>
|
</label>
|
||||||
<label class="block">
|
<label class="block">
|
||||||
<span class="text-gray-500 font-black uppercase text-[10px] tracking-[0.2em] mb-2 block">Wagering</span>
|
<span
|
||||||
|
class="mb-2 block text-[10px] font-black tracking-[0.2em] text-gray-500 uppercase"
|
||||||
|
>Wagering</span
|
||||||
|
>
|
||||||
<div class="relative">
|
<div class="relative">
|
||||||
<RotateCw class="absolute left-4 top-1/2 -translate-y-1/2 text-gray-600" :size="14" />
|
<RotateCw
|
||||||
<input v-model="form.wagering" type="text" class="form-input pl-10" placeholder="35x">
|
class="absolute top-1/2 left-4 -translate-y-1/2 text-gray-600"
|
||||||
|
:size="14"
|
||||||
|
/>
|
||||||
|
<input
|
||||||
|
v-model="form.wagering"
|
||||||
|
type="text"
|
||||||
|
class="form-input pl-10"
|
||||||
|
placeholder="35x"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</label>
|
</label>
|
||||||
<label class="block">
|
<label class="block">
|
||||||
<span class="text-gray-500 font-black uppercase text-[10px] tracking-[0.2em] mb-2 block">Free Spins</span>
|
<span
|
||||||
|
class="mb-2 block text-[10px] font-black tracking-[0.2em] text-gray-500 uppercase"
|
||||||
|
>Free Spins</span
|
||||||
|
>
|
||||||
<div class="relative">
|
<div class="relative">
|
||||||
<Award class="absolute left-4 top-1/2 -translate-y-1/2 text-gray-600" :size="14" />
|
<Award
|
||||||
<input v-model="form.free_spins" type="text" class="form-input pl-10" placeholder="100 FS">
|
class="absolute top-1/2 left-4 -translate-y-1/2 text-gray-600"
|
||||||
|
:size="14"
|
||||||
|
/>
|
||||||
|
<input
|
||||||
|
v-model="form.free_spins"
|
||||||
|
type="text"
|
||||||
|
class="form-input pl-10"
|
||||||
|
placeholder="100 FS"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<label class="block">
|
<label class="block">
|
||||||
<span class="text-gray-500 font-black uppercase text-[10px] tracking-[0.2em] mb-2 block">Affiliate / Button Link</span>
|
<span
|
||||||
|
class="mb-2 block text-[10px] font-black tracking-[0.2em] text-gray-500 uppercase"
|
||||||
|
>Affiliate / Button Link</span
|
||||||
|
>
|
||||||
<div class="relative">
|
<div class="relative">
|
||||||
<LinkIcon class="absolute left-4 top-1/2 -translate-y-1/2 text-gray-600" :size="14" />
|
<LinkIcon
|
||||||
<input v-model="form.button_link" type="text" class="form-input pl-10" placeholder="https://...">
|
class="absolute top-1/2 left-4 -translate-y-1/2 text-gray-600"
|
||||||
|
:size="14"
|
||||||
|
/>
|
||||||
|
<input
|
||||||
|
v-model="form.button_link"
|
||||||
|
type="text"
|
||||||
|
class="form-input pl-10"
|
||||||
|
placeholder="https://..."
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</label>
|
</label>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<section class="space-y-6">
|
<section class="space-y-6">
|
||||||
<h2 class="text-xl font-black italic uppercase tracking-tight text-orange-400 flex items-center gap-3">
|
<h2
|
||||||
<span class="w-8 h-[2px] bg-orange-400"></span> Configuration
|
class="flex items-center gap-3 text-xl font-black tracking-tight text-orange-400 uppercase italic"
|
||||||
|
>
|
||||||
|
<span class="h-[2px] w-8 bg-orange-400"></span>
|
||||||
|
Configuration
|
||||||
</h2>
|
</h2>
|
||||||
|
|
||||||
<div class="flex flex-wrap gap-6">
|
<div class="flex flex-wrap gap-6">
|
||||||
<label class="flex items-center gap-3 group cursor-pointer">
|
<label
|
||||||
<div class="relative w-12 h-6 bg-white/5 rounded-full border border-white/10 transition group-hover:border-orange-500/50">
|
class="group flex cursor-pointer items-center gap-3"
|
||||||
<input v-model="form.is_sticky" type="checkbox" class="sr-only peer">
|
>
|
||||||
<div class="absolute left-1 top-1 w-4 h-4 bg-gray-500 rounded-full transition-all peer-checked:left-7 peer-checked:bg-orange-500"></div>
|
<div
|
||||||
|
class="relative h-6 w-12 rounded-full border border-white/10 bg-white/5 transition group-hover:border-orange-500/50"
|
||||||
|
>
|
||||||
|
<input
|
||||||
|
v-model="form.is_sticky"
|
||||||
|
type="checkbox"
|
||||||
|
class="peer sr-only"
|
||||||
|
/>
|
||||||
|
<div
|
||||||
|
class="absolute top-1 left-1 h-4 w-4 rounded-full bg-gray-500 transition-all peer-checked:left-7 peer-checked:bg-orange-500"
|
||||||
|
></div>
|
||||||
</div>
|
</div>
|
||||||
<span class="text-[10px] font-black uppercase tracking-widest text-gray-400 peer-checked:text-white">Sticky Bonus</span>
|
<span
|
||||||
|
class="text-[10px] font-black tracking-widest text-gray-400 uppercase peer-checked:text-white"
|
||||||
|
>Sticky Bonus</span
|
||||||
|
>
|
||||||
</label>
|
</label>
|
||||||
|
|
||||||
<label class="flex items-center gap-3 group cursor-pointer">
|
<label
|
||||||
<div class="relative w-12 h-6 bg-white/5 rounded-full border border-white/10 transition group-hover:border-cyan-500/50">
|
class="group flex cursor-pointer items-center gap-3"
|
||||||
<input v-model="form.is_no_deposit" type="checkbox" class="sr-only peer">
|
>
|
||||||
<div class="absolute left-1 top-1 w-4 h-4 bg-gray-500 rounded-full transition-all peer-checked:left-7 peer-checked:bg-cyan-500"></div>
|
<div
|
||||||
|
class="relative h-6 w-12 rounded-full border border-white/10 bg-white/5 transition group-hover:border-cyan-500/50"
|
||||||
|
>
|
||||||
|
<input
|
||||||
|
v-model="form.is_no_deposit"
|
||||||
|
type="checkbox"
|
||||||
|
class="peer sr-only"
|
||||||
|
/>
|
||||||
|
<div
|
||||||
|
class="absolute top-1 left-1 h-4 w-4 rounded-full bg-gray-500 transition-all peer-checked:left-7 peer-checked:bg-cyan-500"
|
||||||
|
></div>
|
||||||
</div>
|
</div>
|
||||||
<span class="text-[10px] font-black uppercase tracking-widest text-gray-400">No Deposit</span>
|
<span
|
||||||
|
class="text-[10px] font-black tracking-widest text-gray-400 uppercase"
|
||||||
|
>No Deposit</span
|
||||||
|
>
|
||||||
</label>
|
</label>
|
||||||
|
|
||||||
<label class="flex items-center gap-3 group cursor-pointer">
|
<label
|
||||||
<div class="relative w-12 h-6 bg-white/5 rounded-full border border-white/10 transition group-hover:border-yellow-500/50">
|
class="group flex cursor-pointer items-center gap-3"
|
||||||
<input v-model="form.is_featured" type="checkbox" class="sr-only peer">
|
>
|
||||||
<div class="absolute left-1 top-1 w-4 h-4 bg-gray-500 rounded-full transition-all peer-checked:left-7 peer-checked:bg-yellow-500"></div>
|
<div
|
||||||
|
class="relative h-6 w-12 rounded-full border border-white/10 bg-white/5 transition group-hover:border-yellow-500/50"
|
||||||
|
>
|
||||||
|
<input
|
||||||
|
v-model="form.is_featured"
|
||||||
|
type="checkbox"
|
||||||
|
class="peer sr-only"
|
||||||
|
/>
|
||||||
|
<div
|
||||||
|
class="absolute top-1 left-1 h-4 w-4 rounded-full bg-gray-500 transition-all peer-checked:left-7 peer-checked:bg-yellow-500"
|
||||||
|
></div>
|
||||||
</div>
|
</div>
|
||||||
<span class="text-[10px] font-black uppercase tracking-widest text-gray-400 flex items-center gap-2"><Star :size="12" /> Super Card</span>
|
<span
|
||||||
|
class="flex items-center gap-2 text-[10px] font-black tracking-widest text-gray-400 uppercase"
|
||||||
|
><Star :size="12" /> Super Card</span
|
||||||
|
>
|
||||||
</label>
|
</label>
|
||||||
|
|
||||||
<label class="flex items-center gap-4 ml-auto">
|
<label class="ml-auto flex items-center gap-4">
|
||||||
<span class="text-[10px] font-black uppercase tracking-widest text-gray-500">Sort Order</span>
|
<span
|
||||||
<input v-model="form.order" type="number" class="form-input w-20 text-center">
|
class="text-[10px] font-black tracking-widest text-gray-500 uppercase"
|
||||||
|
>Sort Order</span
|
||||||
|
>
|
||||||
|
<input
|
||||||
|
v-model="form.order"
|
||||||
|
type="number"
|
||||||
|
class="form-input w-20 text-center"
|
||||||
|
/>
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Badges -->
|
<!-- Badges -->
|
||||||
<div class="space-y-4">
|
<div class="space-y-4">
|
||||||
<span class="text-gray-500 font-black uppercase text-[10px] tracking-[0.2em] block">Status Badges</span>
|
<span
|
||||||
<div class="flex flex-wrap gap-2 mb-2">
|
class="block text-[10px] font-black tracking-[0.2em] text-gray-500 uppercase"
|
||||||
<div v-for="(badge, idx) in form.badges" :key="idx"
|
>Status Badges</span
|
||||||
:class="['flex items-center gap-2 px-3 py-1.5 rounded-lg group hover:border-red-500/30 transition', badge.class || 'bg-white/5 border border-white/10']">
|
>
|
||||||
<span class="text-[10px] font-bold uppercase">{{ badge.label }}</span>
|
<div class="mb-2 flex flex-wrap gap-2">
|
||||||
<button type="button" @click="removeBadge(idx)" class="text-gray-600 group-hover:text-red-500 transition">
|
<div
|
||||||
|
v-for="(badge, idx) in form.badges"
|
||||||
|
:key="idx"
|
||||||
|
:class="[
|
||||||
|
'group flex items-center gap-2 rounded-lg px-3 py-1.5 transition hover:border-red-500/30',
|
||||||
|
badge.class ||
|
||||||
|
'border border-white/10 bg-white/5',
|
||||||
|
]"
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
class="text-[10px] font-bold uppercase"
|
||||||
|
>{{ badge.label }}</span
|
||||||
|
>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
@click="removeBadge(idx)"
|
||||||
|
class="text-gray-600 transition group-hover:text-red-500"
|
||||||
|
>
|
||||||
<Trash2 :size="12" />
|
<Trash2 :size="12" />
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex flex-wrap gap-2 border-t border-white/5 pt-4">
|
<div
|
||||||
<span class="text-gray-500 text-xs font-bold uppercase w-full">Predefined:</span>
|
class="flex flex-wrap gap-2 border-t border-white/5 pt-4"
|
||||||
<button type="button" v-for="badge in predefinedBadges" :key="badge.label"
|
>
|
||||||
@click="addPredefinedBadge(badge)"
|
<span
|
||||||
:class="['px-3 py-1.5 rounded-lg text-[10px] font-bold uppercase transition', badge.class, form.badges.some(b => b.label === badge.label) ? 'opacity-50 cursor-not-allowed' : 'hover:opacity-75']"
|
class="w-full text-xs font-bold text-gray-500 uppercase"
|
||||||
:disabled="form.badges.some(b => b.label === badge.label)">
|
>Predefined:</span
|
||||||
|
>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
v-for="badge in predefinedBadges"
|
||||||
|
:key="badge.label"
|
||||||
|
@click="addPredefinedBadge(badge)"
|
||||||
|
:class="[
|
||||||
|
'rounded-lg px-3 py-1.5 text-[10px] font-bold uppercase transition',
|
||||||
|
badge.class,
|
||||||
|
form.badges.some(
|
||||||
|
(b) => b.label === badge.label,
|
||||||
|
)
|
||||||
|
? 'cursor-not-allowed opacity-50'
|
||||||
|
: 'hover:opacity-75',
|
||||||
|
]"
|
||||||
|
:disabled="
|
||||||
|
form.badges.some(
|
||||||
|
(b) => b.label === badge.label,
|
||||||
|
)
|
||||||
|
"
|
||||||
|
>
|
||||||
{{ badge.label }}
|
{{ badge.label }}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex gap-2 w-full mt-2">
|
<div class="mt-2 flex w-full gap-2">
|
||||||
<input v-model="newBadge" type="text" class="form-input flex-1 text-xs py-2" placeholder="Add Custom Badge (e.g. VIP DEAL)">
|
<input
|
||||||
<button type="button" @click="addBadge" class="btn-secondary py-2"><Plus :size="14" /></button>
|
v-model="newBadge"
|
||||||
|
type="text"
|
||||||
|
class="form-input flex-1 py-2 text-xs"
|
||||||
|
placeholder="Add Custom Badge (e.g. VIP DEAL)"
|
||||||
|
/>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
@click="addBadge"
|
||||||
|
class="btn-secondary py-2"
|
||||||
|
>
|
||||||
|
<Plus :size="14" />
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Key Features -->
|
<!-- Key Features -->
|
||||||
<div class="space-y-4">
|
<div class="space-y-4">
|
||||||
<span class="text-gray-500 font-black uppercase text-[10px] tracking-[0.2em] block">Key Features (Pros)</span>
|
<span
|
||||||
<div class="space-y-2 mb-2">
|
class="block text-[10px] font-black tracking-[0.2em] text-gray-500 uppercase"
|
||||||
<div v-for="(feature, idx) in form.key_features" :key="idx"
|
>Key Features (Pros)</span
|
||||||
class="flex items-center justify-between bg-white/[0.02] border border-white/5 p-3 rounded-xl">
|
>
|
||||||
<span class="text-xs text-gray-300">{{ feature }}</span>
|
<div class="mb-2 space-y-2">
|
||||||
<button type="button" @click="removeFeature(idx)" class="text-gray-600 hover:text-red-500 transition">
|
<div
|
||||||
|
v-for="(feature, idx) in form.key_features"
|
||||||
|
:key="idx"
|
||||||
|
class="flex items-center justify-between rounded-xl border border-white/5 bg-white/[0.02] p-3"
|
||||||
|
>
|
||||||
|
<span class="text-xs text-gray-300">{{
|
||||||
|
feature
|
||||||
|
}}</span>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
@click="removeFeature(idx)"
|
||||||
|
class="text-gray-600 transition hover:text-red-500"
|
||||||
|
>
|
||||||
<Trash2 :size="14" />
|
<Trash2 :size="14" />
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex flex-wrap gap-2 border-t border-white/5 pt-4">
|
<div
|
||||||
<span class="text-gray-500 text-xs font-bold uppercase w-full">Predefined:</span>
|
class="flex flex-wrap gap-2 border-t border-white/5 pt-4"
|
||||||
<button type="button" v-for="feature in predefinedKeyFeatures" :key="feature"
|
>
|
||||||
@click="addPredefinedFeature(feature)"
|
<span
|
||||||
:class="['px-3 py-1.5 rounded-lg text-[10px] font-bold uppercase bg-white/5 border border-white/10 transition', form.key_features.includes(feature) ? 'opacity-50 cursor-not-allowed' : 'hover:opacity-75']"
|
class="w-full text-xs font-bold text-gray-500 uppercase"
|
||||||
:disabled="form.key_features.includes(feature)">
|
>Predefined:</span
|
||||||
|
>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
v-for="feature in predefinedKeyFeatures"
|
||||||
|
:key="feature"
|
||||||
|
@click="addPredefinedFeature(feature)"
|
||||||
|
:class="[
|
||||||
|
'rounded-lg border border-white/10 bg-white/5 px-3 py-1.5 text-[10px] font-bold uppercase transition',
|
||||||
|
form.key_features.includes(feature)
|
||||||
|
? 'cursor-not-allowed opacity-50'
|
||||||
|
: 'hover:opacity-75',
|
||||||
|
]"
|
||||||
|
:disabled="
|
||||||
|
form.key_features.includes(feature)
|
||||||
|
"
|
||||||
|
>
|
||||||
{{ feature }}
|
{{ feature }}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex gap-2 w-full mt-2">
|
<div class="mt-2 flex w-full gap-2">
|
||||||
<input v-model="newFeature" type="text" class="form-input flex-1 text-xs py-2" placeholder="Add Custom Feature (e.g. Instant Rakeback)">
|
<input
|
||||||
<button type="button" @click="addFeature" class="btn-secondary py-2"><Plus :size="14" /></button>
|
v-model="newFeature"
|
||||||
|
type="text"
|
||||||
|
class="form-input flex-1 py-2 text-xs"
|
||||||
|
placeholder="Add Custom Feature (e.g. Instant Rakeback)"
|
||||||
|
/>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
@click="addFeature"
|
||||||
|
class="btn-secondary py-2"
|
||||||
|
>
|
||||||
|
<Plus :size="14" />
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="pt-10 border-t border-white/5 flex justify-end gap-4">
|
<div class="flex justify-end gap-4 border-t border-white/5 pt-10">
|
||||||
<Link href="/admin/bonuses" class="px-8 py-4 rounded-2xl text-xs font-black uppercase tracking-widest text-gray-500 hover:text-white transition">Cancel</Link>
|
<Link
|
||||||
<button type="submit" class="btn-primary flex items-center gap-3" :disabled="form.processing">
|
href="/admin/bonuses"
|
||||||
|
class="rounded-2xl px-8 py-4 text-xs font-black tracking-widest text-gray-500 uppercase transition hover:text-white"
|
||||||
|
>Cancel</Link
|
||||||
|
>
|
||||||
|
<button
|
||||||
|
type="submit"
|
||||||
|
class="btn-primary flex items-center gap-3"
|
||||||
|
:disabled="form.processing"
|
||||||
|
>
|
||||||
{{ form.processing ? 'Saving...' : 'Save Bonus' }}
|
{{ form.processing ? 'Saving...' : 'Save Bonus' }}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
@@ -342,27 +638,28 @@ const submit = () => {
|
|||||||
<style scoped>
|
<style scoped>
|
||||||
@reference "../../../../css/app.css";
|
@reference "../../../../css/app.css";
|
||||||
|
|
||||||
.form-input, .form-textarea {
|
.form-input,
|
||||||
@apply w-full bg-white/[0.03] border border-white/5 rounded-2xl py-4 px-6 outline-none focus:border-blue-500/50 transition focus:ring-1 focus:ring-blue-500/20 text-white placeholder-gray-600 text-sm font-medium;
|
.form-textarea {
|
||||||
|
@apply w-full rounded-2xl border border-white/5 bg-white/[0.03] px-6 py-4 text-sm font-medium text-white placeholder-gray-600 transition outline-none focus:border-blue-500/50 focus:ring-1 focus:ring-blue-500/20;
|
||||||
}
|
}
|
||||||
.form-file-input {
|
.form-file-input {
|
||||||
@apply w-full text-xs text-gray-500
|
@apply w-full text-xs text-gray-500 transition-all duration-300 file:mr-4 file:rounded-2xl file:border-0 file:bg-white/5 file:px-6 file:py-3 file:text-[10px] file:font-black file:tracking-widest file:text-white file:uppercase hover:file:bg-white/10;
|
||||||
file:mr-4 file:py-3 file:px-6
|
|
||||||
file:rounded-2xl file:border-0
|
|
||||||
file:text-[10px] file:font-black file:uppercase file:tracking-widest
|
|
||||||
file:bg-white/5 file:text-white
|
|
||||||
hover:file:bg-white/10 transition-all duration-300;
|
|
||||||
}
|
}
|
||||||
.form-color-input {
|
.form-color-input {
|
||||||
@apply h-14 rounded-2xl border-none bg-white/5 cursor-pointer p-1 overflow-hidden;
|
@apply h-14 cursor-pointer overflow-hidden rounded-2xl border-none bg-white/5 p-1;
|
||||||
|
}
|
||||||
|
.form-color-input::-webkit-color-swatch-wrapper {
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
.form-color-input::-webkit-color-swatch {
|
||||||
|
border: none;
|
||||||
|
border-radius: 12px;
|
||||||
}
|
}
|
||||||
.form-color-input::-webkit-color-swatch-wrapper { padding: 0; }
|
|
||||||
.form-color-input::-webkit-color-swatch { border: none; border-radius: 12px; }
|
|
||||||
|
|
||||||
.btn-primary {
|
.btn-primary {
|
||||||
@apply bg-gradient-to-r from-blue-600 to-purple-600 hover:scale-[1.02] active:scale-[0.98] transition-all duration-300 text-white px-10 py-4 rounded-2xl font-black uppercase tracking-widest text-xs shadow-xl shadow-blue-500/20;
|
@apply rounded-2xl bg-gradient-to-r from-blue-600 to-purple-600 px-10 py-4 text-xs font-black tracking-widest text-white uppercase shadow-xl shadow-blue-500/20 transition-all duration-300 hover:scale-[1.02] active:scale-[0.98];
|
||||||
}
|
}
|
||||||
.btn-secondary {
|
.btn-secondary {
|
||||||
@apply bg-white/5 border border-white/10 text-white px-4 py-3 rounded-xl hover:bg-white/10 transition;
|
@apply rounded-xl border border-white/10 bg-white/5 px-4 py-3 text-white transition hover:bg-white/10;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
Reference in New Issue
Block a user