Improve admin navigation and local API reachability

This commit is contained in:
AzuTear
2026-06-17 13:24:41 +02:00
parent 953257bcef
commit 4a211189f0
11 changed files with 330 additions and 23 deletions
+35 -2
View File
@@ -1,6 +1,7 @@
<script setup lang="ts">
import { computed, reactive, ref, watch } from 'vue'
import AdminPageHeader from '../../components/admin/AdminPageHeader.vue'
import AdminSeasonToolbar from '../../components/admin/AdminSeasonToolbar.vue'
import Button from '../../components/ui/Button.vue'
import Card from '../../components/ui/Card.vue'
@@ -19,6 +20,17 @@ const reviewForms = reactive<Record<number, {
const seasonDetail = computed(() => store.adminSeasonDetail)
const selectedSeasonId = computed(() => store.adminSelectedSeasonId)
const reviewFilter = ref('')
const filteredNominations = computed(() => {
const query = reviewFilter.value.trim().toLowerCase()
if (!query) return seasonDetail.value.pendingNominations
return seasonDetail.value.pendingNominations.filter((nomination) =>
[nomination.categoryName, nomination.candidateText, nomination.submittedByTwitchId]
.join(' ')
.toLowerCase()
.includes(query),
)
})
watch(
seasonDetail,
@@ -71,6 +83,12 @@ async function rejectNomination(nominationId: number) {
<template>
<div class="space-y-6">
<AdminPageHeader
eyebrow="Reviews"
title="Freitext-Nominierungen sichten"
description="Alle uneindeutigen oder noch nicht gemappten Nominierungen laufen hier zusammen. Suche nach User, Kategorie oder Kandidat und entscheide dann direkt im Kontext."
/>
<AdminSeasonToolbar />
<Card class="p-7">
@@ -80,7 +98,7 @@ async function rejectNomination(nominationId: number) {
<p class="mt-2 text-sm text-slate-500">Freitext-Nominierungen und Alias-Faelle, die das Team direkt in Kandidaten ueberfuehren oder verwerfen kann.</p>
</div>
<span class="text-sm uppercase tracking-[0.2em] text-slate-500">
{{ seasonDetail.pendingNominations.length }} offen
{{ filteredNominations.length }} / {{ seasonDetail.pendingNominations.length }} offen
</span>
</div>
@@ -91,9 +109,21 @@ async function rejectNomination(nominationId: number) {
{{ adminError }}
</p>
<div class="mt-6 grid gap-4 md:grid-cols-[minmax(0,1fr)_220px]">
<input
v-model="reviewFilter"
type="text"
class="rounded-2xl border border-violet-200 px-4 py-3"
placeholder="Nach Kategorie, Nominierung oder User filtern"
/>
<div class="rounded-2xl border border-violet-100 bg-violet-50/60 px-4 py-3 text-sm text-slate-600">
Tipp: Suche erst nach dem Problemfall, dann entscheide uebernehmen oder verwerfen.
</div>
</div>
<div class="mt-6 space-y-4">
<div
v-for="nomination in seasonDetail.pendingNominations"
v-for="nomination in filteredNominations"
:key="nomination.id"
class="rounded-[26px] border border-violet-100 bg-white/90 p-5"
>
@@ -144,6 +174,9 @@ async function rejectNomination(nominationId: number) {
<p v-if="seasonDetail.pendingNominations.length === 0" class="rounded-[26px] border border-dashed border-violet-100 px-5 py-6 text-sm text-slate-500">
Keine offenen Review-Faelle in der aktuell gewaehlten Season.
</p>
<p v-else-if="filteredNominations.length === 0" class="rounded-[26px] border border-dashed border-violet-100 px-5 py-6 text-sm text-slate-500">
Keine Review-Faelle passen zum aktuellen Filter.
</p>
</div>
</Card>
</div>