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,110 @@
<script setup lang="ts">
import { Head, router } from '@inertiajs/vue3';
import { onMounted, ref, nextTick } from 'vue';
import CasinoAdminLayout from '@/layouts/admin/CasinoAdminLayout.vue';
const props = defineProps<{ aiEnabled?: boolean }>();
const ai = ref(!!props.aiEnabled);
const toggling = ref(false);
async function toggleAi() {
toggling.value = true;
try {
await router.post('/admin/chat/toggle-ai', { enabled: ai.value }, { preserveScroll: true });
} finally {
toggling.value = false;
}
}
const messages = ref<any[]>([]);
const loading = ref(false);
async function loadMessages() {
loading.value = true;
try {
const res = await fetch('/api/chat?limit=50');
if (res.ok) {
const json = await res.json();
messages.value = json?.data || [];
}
} finally {
loading.value = false;
nextTick(() => { if ((window as any).lucide) (window as any).lucide.createIcons(); });
}
}
onMounted(() => {
loadMessages();
});
</script>
<template>
<CasinoAdminLayout>
<Head title="Admin Live Chat" />
<template #title>
Live Chat Management
</template>
<template #actions>
<label class="switch">
<input type="checkbox" v-model="ai" @change="toggleAi" :disabled="toggling" />
<span class="slider"></span>
<span class="ml-2 text-sm" :class="ai ? 'text-green' : 'text-muted'">AI {{ ai ? 'Enabled' : 'Disabled' }}</span>
</label>
</template>
<div class="panel">
<div class="panel-header">
<h3>Recent Messages</h3>
<button class="btn-ghost" @click="loadMessages" :disabled="loading">
<i data-lucide="refresh-ccw"></i> Refresh
</button>
</div>
<div class="chat-list">
<div v-for="m in messages" :key="m.id" class="chat-item">
<div class="avatar">{{ m.user?.username?.charAt(0)?.toUpperCase() || '?' }}</div>
<div class="content">
<div class="meta">
<span class="name">{{ m.user?.username || 'Unknown' }}</span>
<span class="time">{{ new Date(m.created_at).toLocaleString() }}</span>
</div>
<div class="text">{{ m.message }}</div>
</div>
<form :action="`/admin/chat/${m.id}`" method="post" class="actions" @submit.prevent="$el.submit()">
<input type="hidden" name="_method" value="DELETE" />
<button class="btn-danger" title="Delete message"><i data-lucide="trash-2"></i></button>
</form>
</div>
<div v-if="!messages.length && !loading" class="text-center py-8 text-muted">No messages yet.</div>
</div>
</div>
</CasinoAdminLayout>
</template>
<style scoped>
.panel { background: #111113; border: 1px solid #1f1f22; border-radius: 16px; }
.panel-header { display: flex; justify-content: space-between; align-items: center; padding: 16px 20px; border-bottom: 1px solid #1f1f22; }
.chat-list { display: flex; flex-direction: column; }
.chat-item { display: grid; grid-template-columns: 40px 1fr auto; gap: 12px; padding: 14px 20px; border-bottom: 1px solid #1f1f22; }
.avatar { width: 40px; height: 40px; border-radius: 50%; background: #27272a; color: #fff; display: flex; align-items: center; justify-content: center; font-weight: 800; }
.meta { display: flex; gap: 8px; align-items: baseline; }
.meta .name { font-weight: 700; color: #fff; }
.meta .time { color: #a1a1aa; font-size: 12px; }
.text { color: #e4e4e7; }
.actions { display: flex; align-items: center; gap: 8px; }
.btn-ghost { background: transparent; border: none; color: #a1a1aa; display: inline-flex; align-items: center; gap: 6px; cursor: pointer; }
.btn-ghost:hover { color: #fff; }
.btn-danger { background: transparent; border: 1px solid #7f1d1d; color: #ef4444; padding: 6px 10px; border-radius: 8px; cursor: pointer; }
.btn-danger:hover { background: rgba(239, 68, 68, .1); }
/* Switch */
.switch { display: inline-flex; align-items: center; }
.switch input { display: none; }
.switch .slider { width: 40px; height: 22px; background: #27272a; border-radius: 9999px; position: relative; transition: .2s; display: inline-block; }
.switch .slider:after { content: ''; width: 18px; height: 18px; background: #fff; border-radius: 50%; position: absolute; top: 2px; left: 2px; transition: .2s; }
.switch input:checked + .slider { background: #16a34a; }
.switch input:checked + .slider:after { transform: translateX(18px); }
.text-muted { color: #a1a1aa; }
.text-green { color: #16a34a; }
.text-white { color: #fff; }
</style>