Migrate Event Badges to V3 and implement Core Management pages
- Completed V3 migration for Event Badge CRUD operations - Implemented User module V3 logic and editable fields - Created management routes for Accounts, Sites, Users, and Lookups - Updated Site Domain logic to use 'fqdn' and show 'access_key' - Modernized Core Dashboard with navigation cards - Restored Dexie User table definition
This commit is contained in:
113
src/routes/core/users/+page.svelte
Normal file
113
src/routes/core/users/+page.svelte
Normal file
@@ -0,0 +1,113 @@
|
||||
<script lang="ts">
|
||||
import { onMount } from 'svelte';
|
||||
import { load_ae_obj_li__user, create_ae_obj__user } from '$lib/ae_core/ae_core__user';
|
||||
import { ae_api, ae_loc } from '$lib/stores/ae_stores';
|
||||
import { goto } from '$app/navigation';
|
||||
import { Plus, Search, User, ShieldCheck, Mail } from 'lucide-svelte';
|
||||
|
||||
let user_li: any[] = $state([]);
|
||||
let loading = $state(true);
|
||||
let qry_str = $state('');
|
||||
let qry_enabled = $state('all');
|
||||
|
||||
async function load_users() {
|
||||
loading = true;
|
||||
user_li = await load_ae_obj_li__user({
|
||||
api_cfg: $ae_api,
|
||||
qry_str: qry_str || null,
|
||||
enabled: qry_enabled as any,
|
||||
log_lvl: 1
|
||||
});
|
||||
loading = false;
|
||||
}
|
||||
|
||||
onMount(() => {
|
||||
if (!$ae_loc.manager_access) {
|
||||
goto('/core');
|
||||
return;
|
||||
}
|
||||
load_users();
|
||||
});
|
||||
|
||||
async function handle_add_user() {
|
||||
const username = prompt('Enter new username:');
|
||||
if (!username) return;
|
||||
const email = prompt('Enter email address:');
|
||||
|
||||
await create_ae_obj__user({
|
||||
api_cfg: $ae_api,
|
||||
data_kv: { username, email, enable: true },
|
||||
log_lvl: 1
|
||||
});
|
||||
load_users();
|
||||
}
|
||||
</script>
|
||||
|
||||
<div class="container mx-auto p-4 space-y-4">
|
||||
<header class="flex justify-between items-center">
|
||||
<div class="flex items-center gap-2">
|
||||
<ShieldCheck size={24} />
|
||||
<h1 class="h2">User Management</h1>
|
||||
</div>
|
||||
<button class="btn variant-filled-primary" onclick={handle_add_user}>
|
||||
<Plus size={16} class="mr-2" /> Add User
|
||||
</button>
|
||||
</header>
|
||||
|
||||
<div class="card p-4 variant-soft flex flex-wrap gap-4 items-end">
|
||||
<label class="label flex-1">
|
||||
<span>Search Username or Email</span>
|
||||
<div class="input-group input-group-divider grid-cols-[auto_1fr_auto]">
|
||||
<div class="input-group-shim"><Search size={16} /></div>
|
||||
<input type="search" bind:value={qry_str} placeholder="Search..." onkeydown={(e) => e.key === 'Enter' && load_users()} />
|
||||
<button class="variant-filled-secondary" onclick={load_users}>Go</button>
|
||||
</div>
|
||||
</label>
|
||||
<label class="label">
|
||||
<span>Status</span>
|
||||
<select class="select w-32" bind:value={qry_enabled} onchange={load_users}>
|
||||
<option value="all">All</option>
|
||||
<option value="enabled">Enabled</option>
|
||||
<option value="not_enabled">Disabled</option>
|
||||
</select>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
{#if loading}
|
||||
<div class="placeholder animate-pulse w-full h-64"></div>
|
||||
{:else if user_li.length === 0}
|
||||
<p class="text-center py-12 opacity-60">No users found.</p>
|
||||
{:else}
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
|
||||
{#each user_li as user}
|
||||
<div class="card p-4 space-y-3 variant-soft flex flex-col justify-between">
|
||||
<div class="space-y-2">
|
||||
<header class="flex justify-between items-start">
|
||||
<div class="flex items-center gap-2">
|
||||
<div class="avatar variant-filled-surface w-10 h-10 flex items-center justify-center rounded-full">
|
||||
<User size={20} />
|
||||
</div>
|
||||
<div>
|
||||
<p class="font-bold">{user.username}</p>
|
||||
<p class="text-xs opacity-60">{user.name || '--'}</p>
|
||||
</div>
|
||||
</div>
|
||||
{#if user.super}
|
||||
<span class="badge variant-filled-error">Super</span>
|
||||
{:else if user.manager}
|
||||
<span class="badge variant-filled-warning">Manager</span>
|
||||
{/if}
|
||||
</header>
|
||||
<div class="flex items-center gap-2 text-sm opacity-80">
|
||||
<Mail size={14} />
|
||||
<span>{user.email || '--'}</span>
|
||||
</div>
|
||||
</div>
|
||||
<button class="btn btn-sm variant-filled-primary w-full" onclick={() => goto(`/core/users/${user.user_id_random}`)}>
|
||||
Edit User
|
||||
</button>
|
||||
</div>
|
||||
{/each}
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
Reference in New Issue
Block a user