Files
BetiX/resources/js/pages/Admin/Users.vue
Dolo 0280278978
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
Initialer Laravel Commit für BetiX
2026-04-04 18:01:50 +02:00

143 lines
6.9 KiB
Vue
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<script setup lang="ts">
import { Head, Link, router } from '@inertiajs/vue3';
import { ref } from 'vue';
import CasinoAdminLayout from '@/layouts/admin/CasinoAdminLayout.vue';
const props = defineProps<{
users: any;
roles: string[];
filters: { search: string, role: string };
}>();
const search = ref(props.filters?.search || '');
const filterRole = ref(props.filters?.role || '');
const searchUsers = () => {
router.get(route('admin.users.index'), {
search: search.value,
role: filterRole.value
}, {
preserveState: true,
replace: true
});
};
</script>
<template>
<CasinoAdminLayout>
<Head title="Admin Users" />
<template #title>
User Management
</template>
<template #actions>
<button class="btn-primary">
<i data-lucide="user-plus"></i> Add User
</button>
</template>
<div class="filters-bar">
<div class="search-input">
<i data-lucide="search"></i>
<input type="text" v-model="search" placeholder="Search by ID, Username, Email..." @keyup.enter="searchUsers" />
</div>
<select v-model="filterRole" @change="searchUsers" class="filter-select">
<option value="">All Roles</option>
<option v-for="r in roles" :key="r" :value="r">{{ r }}</option>
</select>
</div>
<div class="table-container">
<table class="admin-table">
<thead>
<tr>
<th>ID</th>
<th>User</th>
<th>Email</th>
<th>Role</th>
<th>Balance</th>
<th>Status</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
<tr v-for="user in users.data" :key="user.id">
<td class="font-mono text-muted">{{ user.id }}</td>
<td class="font-bold text-white flex items-center gap-3">
<div class="avatar">{{ user.username.charAt(0).toUpperCase() }}</div>
{{ user.username }}
</td>
<td class="text-muted">{{ user.email }}</td>
<td>
<span class="badge" :class="{'bg-red': user.role === 'Admin', 'bg-blue': user.role === 'Moderator', 'bg-gray': user.role === 'User'}">
{{ user.role }}
</span>
</td>
<td class="font-mono text-white">${{ user.balance }}</td>
<td>
<span v-if="user.is_banned" class="badge bg-red-dim text-red">BANNED</span>
<span v-else-if="user.is_chat_banned" class="badge bg-orange-dim text-orange">MUTED</span>
<span v-else class="badge bg-green-dim text-green">ACTIVE</span>
</td>
<td>
<div class="flex items-center gap-2">
<Link :href="`/admin/users/${user.id}`" class="btn-icon" title="View Profile">
<i data-lucide="eye"></i>
</Link>
<Link :href="`/admin/users/${user.id}?tab=finances`" class="btn-icon text-green-400" title="Manage Finances">
<i data-lucide="wallet"></i>
</Link>
<button class="btn-icon text-red-400" title="Ban User" v-if="!user.is_banned">
<i data-lucide="ban"></i>
</button>
</div>
</td>
</tr>
</tbody>
</table>
<div class="pagination" v-if="users.last_page > 1">
<!-- Pagination logic here -->
<span class="text-muted">Page {{ users.current_page }} of {{ users.last_page }}</span>
</div>
</div>
</CasinoAdminLayout>
</template>
<style scoped>
.btn-primary { background: #ff007a; color: white; border: none; padding: 10px 16px; border-radius: 8px; font-weight: 700; cursor: pointer; display: inline-flex; align-items: center; gap: 8px; transition: 0.2s; }
.btn-primary:hover { background: #e6006e; }
.filters-bar { display: flex; gap: 16px; margin-bottom: 24px; }
.search-input { position: relative; flex: 1; max-width: 400px; }
.search-input i { position: absolute; left: 14px; top: 50%; transform: translateY(-50%); color: #a1a1aa; width: 18px; height: 18px; }
.search-input input { width: 100%; background: #111113; border: 1px solid #1f1f22; border-radius: 10px; padding: 12px 12px 12px 40px; color: #fff; font-size: 14px; outline: none; }
.search-input input:focus { border-color: #3f3f46; }
.filter-select { background: #111113; border: 1px solid #1f1f22; border-radius: 10px; padding: 12px 16px; color: #fff; font-size: 14px; outline: none; min-width: 150px; }
.table-container { background: #111113; border: 1px solid #1f1f22; border-radius: 16px; overflow: hidden; }
.admin-table { width: 100%; border-collapse: collapse; text-align: left; }
.admin-table th { background: #0c0c0e; padding: 16px; font-size: 12px; font-weight: 700; color: #a1a1aa; text-transform: uppercase; border-bottom: 1px solid #1f1f22; }
.admin-table td { padding: 16px; border-bottom: 1px solid #1f1f22; font-size: 14px; color: #e4e4e7; }
.admin-table tr:last-child td { border-bottom: none; }
.admin-table tr:hover td { background: #18181b; }
.avatar { width: 32px; height: 32px; background: #27272a; border-radius: 50%; display: flex; align-items: center; justify-content: center; font-weight: 800; color: #fff; }
.badge { padding: 4px 8px; border-radius: 6px; font-size: 11px; font-weight: 800; text-transform: uppercase; }
.bg-red { background: #ef4444; color: #fff; }
.bg-blue { background: #3b82f6; color: #fff; }
.bg-gray { background: #27272a; color: #a1a1aa; }
.bg-red-dim { background: rgba(239, 68, 68, 0.1); border: 1px solid rgba(239, 68, 68, 0.2); }
.bg-orange-dim { background: rgba(245, 158, 11, 0.1); border: 1px solid rgba(245, 158, 11, 0.2); }
.bg-green-dim { background: rgba(16, 185, 129, 0.1); border: 1px solid rgba(16, 185, 129, 0.2); }
.text-red { color: #ef4444; }
.text-orange { color: #f59e0b; }
.text-green { color: #10b981; }
.text-muted { color: #a1a1aa; }
.btn-icon { display: inline-flex; background: transparent; border: none; color: #a1a1aa; cursor: pointer; padding: 8px; border-radius: 8px; transition: 0.2s; text-decoration: none; }
.btn-icon:hover { background: #27272a; color: #fff; }
.pagination { padding: 16px; border-top: 1px solid #1f1f22; display: flex; justify-content: center; }
</style>