heavily simplify server and app content. unify styling
All checks were successful
ci/woodpecker/pr/pr Pipeline was successful

This commit is contained in:
Madison Grubb
2026-02-13 23:36:17 -05:00
parent 1a143d2f8e
commit 1668ec4230
40 changed files with 595 additions and 933 deletions

View File

@@ -1,6 +1,6 @@
<template>
<div class="p-6">
<h2 class="mb-2 text-xl font-semibold tracking-wide text-kestrel-text [text-shadow:0_0_8px_rgba(34,201,201,0.25)]">
<h2 class="kestrel-page-heading mb-2">
Members
</h2>
<p
@@ -10,7 +10,7 @@
Sign in to view members.
</p>
<p
v-else-if="!canViewMembers"
v-else-if="!canEditPois"
class="text-sm text-kestrel-muted"
>
You don't have access to the members list.
@@ -149,7 +149,7 @@
v-if="openRoleDropdownId && dropdownPlacement"
ref="dropdownMenuRef"
role="menu"
class="fixed z-[100] min-w-[6rem] rounded border border-kestrel-border bg-kestrel-surface py-1 shadow-glow [box-shadow:0_4px_12px_-2px_rgba(34,201,201,0.15)]"
class="fixed z-[100] min-w-[6rem] rounded border border-kestrel-border bg-kestrel-surface py-1 shadow-glow shadow-glow-dropdown"
:style="{
top: `${dropdownPlacement.top}px`,
left: `${dropdownPlacement.left}px`,
@@ -183,7 +183,7 @@
@click.self="closeAddUserModal"
>
<div
class="w-full max-w-sm rounded border border-kestrel-border bg-kestrel-surface p-4 shadow-glow"
class="kestrel-card-modal w-full max-w-sm p-4"
@click.stop
>
<h3
@@ -204,7 +204,7 @@
type="text"
required
autocomplete="username"
class="rounded border border-kestrel-border bg-kestrel-bg px-2 py-1.5 text-sm text-kestrel-text"
class="kestrel-input"
placeholder="username"
>
</div>
@@ -219,7 +219,7 @@
type="password"
required
autocomplete="new-password"
class="rounded border border-kestrel-border bg-kestrel-bg px-2 py-1.5 text-sm text-kestrel-text"
class="kestrel-input"
placeholder="••••••••"
>
</div>
@@ -231,7 +231,7 @@
<select
id="add-role"
v-model="newUser.role"
class="rounded border border-kestrel-border bg-kestrel-bg px-2 py-1.5 text-sm text-kestrel-text"
class="kestrel-input"
>
<option value="member">
member
@@ -253,7 +253,7 @@
<div class="flex justify-end gap-2">
<button
type="button"
class="rounded border border-kestrel-border px-3 py-1.5 text-sm text-kestrel-text hover:bg-kestrel-surface-hover"
class="kestrel-btn-secondary"
@click="closeAddUserModal"
>
Cancel
@@ -280,7 +280,7 @@
@click.self="deleteConfirmUser = null"
>
<div
class="w-full max-w-sm rounded border border-kestrel-border bg-kestrel-surface p-4 shadow-glow"
class="kestrel-card-modal w-full max-w-sm p-4"
@click.stop
>
<h3
@@ -295,7 +295,7 @@
<div class="flex justify-end gap-2">
<button
type="button"
class="rounded border border-kestrel-border px-3 py-1.5 text-sm text-kestrel-text hover:bg-kestrel-surface-hover"
class="kestrel-btn-secondary"
@click="deleteConfirmUser = null"
>
Cancel
@@ -318,7 +318,7 @@
@click.self="editUserModal = null"
>
<div
class="w-full max-w-sm rounded border border-kestrel-border bg-kestrel-surface p-4 shadow-glow"
class="kestrel-card-modal w-full max-w-sm p-4"
role="dialog"
aria-modal="true"
aria-labelledby="edit-user-title"
@@ -340,7 +340,7 @@
v-model="editForm.identifier"
type="text"
required
class="rounded border border-kestrel-border bg-kestrel-bg px-2 py-1.5 text-sm text-kestrel-text"
class="kestrel-input"
>
</div>
<div class="mb-4 flex flex-col gap-1">
@@ -353,7 +353,7 @@
v-model="editForm.password"
type="password"
autocomplete="new-password"
class="rounded border border-kestrel-border bg-kestrel-bg px-2 py-1.5 text-sm text-kestrel-text"
class="kestrel-input"
placeholder="••••••••"
>
<p class="mt-0.5 text-xs text-kestrel-muted">
@@ -369,7 +369,7 @@
<div class="flex justify-end gap-2">
<button
type="button"
class="rounded border border-kestrel-border px-3 py-1.5 text-sm text-kestrel-text hover:bg-kestrel-surface-hover"
class="kestrel-btn-secondary"
@click="editUserModal = null"
>
Cancel
@@ -390,15 +390,14 @@
</template>
<script setup>
const { user, isAdmin, refresh: refreshUser } = useUser()
const canViewMembers = computed(() => user.value?.role === 'admin' || user.value?.role === 'leader')
const { user, isAdmin, canEditPois, refresh: refreshUser } = useUser()
const { data: usersData, refresh: refreshUsers } = useAsyncData(
'users',
() => $fetch('/api/users').catch(() => []),
{ default: () => [] },
)
const users = computed(() => (Array.isArray(usersData.value) ? usersData.value : []))
const users = computed(() => Object.freeze([...(usersData.value ?? [])]))
const roleOptions = ['admin', 'leader', 'member']
const pendingRoleUpdates = ref({})
@@ -428,8 +427,8 @@ function setDropdownWrapRef(userId, el) {
}
}
watch(user, (u) => {
if (u?.role === 'admin' || u?.role === 'leader') refreshUsers()
watch(user, () => {
if (canEditPois.value) refreshUsers()
}, { immediate: true })
function toggleRoleDropdown(userId) {