Initialer Laravel Commit für BetiX
Some checks failed
linter / quality (push) Has been cancelled
tests / ci (8.4) (push) Has been cancelled
tests / ci (8.5) (push) Has been cancelled

This commit is contained in:
2026-04-04 18:01:50 +02:00
commit 0280278978
374 changed files with 65210 additions and 0 deletions

View File

@@ -0,0 +1,137 @@
<script setup lang="ts">
import { Head, router } from '@inertiajs/vue3';
import { ref } from 'vue';
import { Button } from '@/components/ui/button';
import { Input } from '@/components/ui/input';
import UserLayout from '@/layouts/admin/CasinoAdminLayout.vue';
const props = defineProps<{ promos: any }>();
const form = ref({
code: '',
description: '',
bonus_amount: 0,
wager_multiplier: 30,
per_user_limit: 1,
global_limit: null as number | null,
starts_at: '',
ends_at: '',
min_deposit: null as number | null,
bonus_expires_days: 7 as number | null,
is_active: true,
});
function toUtcIso(dt: string): string | null {
if (!dt) return null;
// Interpret the datetime-local as local time and convert to UTC ISO string
const d = new Date(dt);
if (isNaN(d.getTime())) return null;
return d.toISOString();
}
function submitCreate() {
const payload = {
...form.value,
starts_at: toUtcIso(form.value.starts_at),
ends_at: toUtcIso(form.value.ends_at),
} as any;
router.post('/admin/promos', payload, {
preserveScroll: true,
});
}
function updatePromo(id: number, data: Record<string, any>) {
const payload: Record<string, any> = { ...data };
if (typeof payload.starts_at === 'string') payload.starts_at = toUtcIso(payload.starts_at);
if (typeof payload.ends_at === 'string') payload.ends_at = toUtcIso(payload.ends_at);
router.patch(`/admin/promos/${id}`, payload, { preserveScroll: true });
}
</script>
<template>
<UserLayout>
<Head title="Admin · Promos" />
<div class="p-4 sm:p-6 lg:p-8">
<h1 class="text-2xl font-bold text-white mb-6">Admin · Promos</h1>
<div class="grid gap-8 md:grid-cols-2">
<!-- Create new promo -->
<div class="rounded-lg border border-[#1f1f1f] p-4 space-y-3 bg-[#0f0f0f]">
<h2 class="font-semibold text-lg text-white">Neue Promo erstellen</h2>
<form class="space-y-3" @submit.prevent="submitCreate">
<div class="grid grid-cols-2 gap-3">
<label class="space-y-1">
<span class="text-sm text-gray-300">Code</span>
<Input v-model="form.code" placeholder="WELCOME10" required />
</label>
<label class="space-y-1">
<span class="text-sm text-gray-300">Bonus Betrag</span>
<Input v-model.number="form.bonus_amount" type="number" min="0" step="0.0001" required />
</label>
<label class="space-y-1">
<span class="text-sm text-gray-300">Wager x</span>
<Input v-model.number="form.wager_multiplier" type="number" min="0" />
</label>
<label class="space-y-1">
<span class="text-sm text-gray-300">Pro User Limit</span>
<Input v-model.number="form.per_user_limit" type="number" min="1" />
</label>
<label class="space-y-1">
<span class="text-sm text-gray-300">Globales Limit</span>
<Input v-model.number="form.global_limit" type="number" min="1" placeholder="optional" />
</label>
<label class="space-y-1">
<span class="text-sm text-gray-300">Min. Einzahlung</span>
<Input v-model.number="form.min_deposit" type="number" min="0" step="0.0001" placeholder="optional" />
</label>
<label class="space-y-1">
<span class="text-sm text-gray-300">Startet am</span>
<Input v-model="form.starts_at" type="datetime-local" />
</label>
<label class="space-y-1">
<span class="text-sm text-gray-300">Endet am</span>
<Input v-model="form.ends_at" type="datetime-local" />
</label>
<label class="space-y-1">
<span class="text-sm text-gray-300">Bonus Ablauf (Tage)</span>
<Input v-model.number="form.bonus_expires_days" type="number" min="1" placeholder="optional" />
</label>
</div>
<label class="inline-flex items-center gap-2 text-gray-300">
<input v-model="form.is_active" type="checkbox" />
<span>Aktiv</span>
</label>
<div class="flex gap-2">
<Button type="submit">Erstellen</Button>
</div>
</form>
</div>
<!-- List promos -->
<div class="rounded-lg border border-[#1f1f1f] p-4 space-y-4 bg-[#0f0f0f]">
<h2 class="font-semibold text-lg text-white">Promos</h2>
<div v-if="props.promos?.data?.length" class="space-y-3">
<div v-for="p in props.promos.data" :key="p.id" class="rounded-md border border-[#1f1f1f] bg-[#141414] p-3 flex flex-col gap-2">
<div class="flex items-center gap-2">
<span class="font-mono text-sm px-2 py-0.5 rounded bg-[#1f1f1f] text-gray-200">{{ p.code }}</span>
<span class="text-xs text-gray-400">Bonus: {{ p.bonus_amount }} · Wager x{{ p.wager_multiplier }}</span>
<span class="ml-auto text-xs" :class="p.is_active ? 'text-emerald-500' : 'text-gray-500'">{{ p.is_active ? 'aktiv' : 'inaktiv' }}</span>
</div>
<div class="grid grid-cols-2 md:grid-cols-4 gap-2 text-xs text-gray-300">
<div>Pro User: {{ p.per_user_limit }}</div>
<div v-if="p.global_limit">Global: {{ p.global_limit }}</div>
<div v-if="p.starts_at">Start: {{ p.starts_at }}</div>
<div v-if="p.ends_at">Ende: {{ p.ends_at }}</div>
</div>
<div class="flex flex-wrap gap-2">
<Button size="sm" variant="secondary" @click="updatePromo(p.id, { is_active: !p.is_active })">{{ p.is_active ? 'Deaktivieren' : 'Aktivieren' }}</Button>
</div>
</div>
</div>
<div v-else class="text-sm text-gray-400">Keine Promos vorhanden.</div>
</div>
</div>
</div>
</UserLayout>
</template>