Replace dashboard day trend with yearly metrics

This commit is contained in:
AzuTear
2026-06-17 14:22:00 +02:00
parent 78bf9fd503
commit 9473ff214a
+51 -31
View File
@@ -51,6 +51,44 @@ const metricCards = computed(() =>
) )
const maxCategoryVotes = computed(() => Math.max(...topCategories.value.map((category) => category.votes), 1)) const maxCategoryVotes = computed(() => Math.max(...topCategories.value.map((category) => category.votes), 1))
const totalCategoryVotes = computed(() => topCategories.value.reduce((sum, category) => sum + category.votes, 0)) const totalCategoryVotes = computed(() => topCategories.value.reduce((sum, category) => sum + category.votes, 0))
const yearTotals = computed(() => [
{
label: 'Nominierungen gesamt',
value: metrics.value.find((metric) => metric.label === 'Nominierungen')?.value ?? 0,
note: `im Award-Jahr ${store.adminSeasonDetail.year}`,
icon: Sparkles,
},
{
label: 'Stimmen gesamt',
value: metrics.value.find((metric) => metric.label === 'Stimmen')?.value ?? 0,
note: 'alle abgegebenen Votes',
icon: BarChart3,
},
{
label: 'Kandidaten',
value: store.adminSeasonDetail.candidates.length,
note: 'fuer Voting und Archiv gepflegt',
icon: Users,
},
{
label: 'Kategorien',
value: store.adminSeasonDetail.categories.length,
note: 'aktive Award-Kategorien',
icon: Tags,
},
{
label: 'Offene Reviews',
value: store.adminSeasonDetail.pendingNominations.length,
note: 'brauchen Team-Entscheidung',
icon: Clock3,
},
{
label: 'Risikohinweise',
value: store.admin.riskFlags.length,
note: 'aktuell offen',
icon: ShieldAlert,
},
])
const priorityActions = computed(() => [ const priorityActions = computed(() => [
{ {
label: 'Reviews bearbeiten', label: 'Reviews bearbeiten',
@@ -85,16 +123,6 @@ const priorityActions = computed(() => [
tone: 'emerald', tone: 'emerald',
}, },
]) ])
const dayTrend = [
{ label: 'Mo', nominations: 48, votes: 62, reviews: 26 },
{ label: 'Di', nominations: 55, votes: 67, reviews: 24 },
{ label: 'Mi', nominations: 51, votes: 74, reviews: 20 },
{ label: 'Do', nominations: 63, votes: 78, reviews: 18 },
{ label: 'Fr', nominations: 69, votes: 86, reviews: 15 },
{ label: 'Sa', nominations: 76, votes: 91, reviews: 13 },
{ label: 'So', nominations: 82, votes: 96, reviews: 12 },
]
const maxDayValue = Math.max(...dayTrend.flatMap((day) => [day.nominations, day.votes, day.reviews]))
</script> </script>
<template> <template>
@@ -207,38 +235,30 @@ const maxDayValue = Math.max(...dayTrend.flatMap((day) => [day.nominations, day.
<Card class="p-7"> <Card class="p-7">
<div class="flex items-center justify-between gap-4"> <div class="flex items-center justify-between gap-4">
<div> <div>
<p class="text-xs font-semibold uppercase tracking-[0.26em] text-violet-500">7-Tage Verlauf</p> <p class="text-xs font-semibold uppercase tracking-[0.26em] text-violet-500">Jahreszahlen</p>
<h2 class="mt-2 font-[Cormorant_Garamond] text-4xl text-violet-800">Aktivitaet nach Tagen</h2> <h2 class="mt-2 font-[Cormorant_Garamond] text-4xl text-violet-800">Gesamtmetriken {{ store.adminSeasonDetail.year }}</h2>
</div> </div>
<BarChart3 class="h-6 w-6 text-amber-500" /> <BarChart3 class="h-6 w-6 text-amber-500" />
</div> </div>
<div class="mt-6 space-y-4"> <div class="mt-6 grid gap-3 sm:grid-cols-2">
<div <div
v-for="day in dayTrend" v-for="item in yearTotals"
:key="day.label" :key="item.label"
class="grid grid-cols-[36px_minmax(0,1fr)] items-center gap-3" class="rounded-[22px] border border-violet-100 bg-white/90 p-4"
> >
<span class="text-sm font-semibold text-slate-500">{{ day.label }}</span> <div class="flex items-start justify-between gap-3">
<div class="space-y-1.5"> <div>
<div class="h-2.5 rounded-full bg-violet-50"> <p class="text-xs font-semibold uppercase tracking-[0.2em] text-violet-500">{{ item.label }}</p>
<div class="h-2.5 rounded-full bg-violet-600" :style="{ width: `${(day.votes / maxDayValue) * 100}%` }" /> <strong class="mt-2 block text-3xl text-violet-900">{{ item.value.toLocaleString('de-DE') }}</strong>
</div> </div>
<div class="h-2.5 rounded-full bg-amber-50"> <div class="grid h-9 w-9 place-items-center rounded-2xl bg-violet-100 text-violet-700">
<div class="h-2.5 rounded-full bg-amber-400" :style="{ width: `${(day.nominations / maxDayValue) * 100}%` }" /> <component :is="item.icon" class="h-4 w-4" />
</div>
<div class="h-2.5 rounded-full bg-emerald-50">
<div class="h-2.5 rounded-full bg-emerald-500" :style="{ width: `${(day.reviews / maxDayValue) * 100}%` }" />
</div> </div>
</div> </div>
<p class="mt-3 text-sm leading-5 text-slate-500">{{ item.note }}</p>
</div> </div>
</div> </div>
<div class="mt-6 flex flex-wrap gap-3 text-xs font-semibold text-slate-600">
<span class="inline-flex items-center gap-2"><i class="h-2.5 w-2.5 rounded-full bg-violet-600" /> Stimmen</span>
<span class="inline-flex items-center gap-2"><i class="h-2.5 w-2.5 rounded-full bg-amber-400" /> Nominierungen</span>
<span class="inline-flex items-center gap-2"><i class="h-2.5 w-2.5 rounded-full bg-emerald-500" /> Reviews offen</span>
</div>
</Card> </Card>
<Card class="p-7"> <Card class="p-7">