admin stuff

This commit is contained in:
Nathan 2026-02-05 12:40:03 -05:00
parent 519abfe02f
commit 90209361b9
2 changed files with 42 additions and 3 deletions

View file

@ -33,7 +33,7 @@ admin.get('/stats', async ({ headers, status }) => {
return status(401, { error: 'Unauthorized' })
}
const [usersCount, projectsCount, totalHoursResult] = await Promise.all([
const [usersCount, projectsCount, totalHoursResult, pendingHoursResult] = await Promise.all([
db.select({ count: sql<number>`count(*)` }).from(usersTable),
db.select({ count: sql<number>`count(*)` })
.from(projectsTable)
@ -43,19 +43,29 @@ admin.get('/stats', async ({ headers, status }) => {
.where(and(
eq(projectsTable.status, 'shipped'),
or(eq(projectsTable.deleted, 0), sql`${projectsTable.deleted} IS NULL`)
)),
db.select({ total: sql<number>`COALESCE(SUM(COALESCE(${projectsTable.hoursOverride}, ${projectsTable.hours})), 0)` })
.from(projectsTable)
.where(and(
eq(projectsTable.status, 'waiting_for_review'),
or(eq(projectsTable.deleted, 0), sql`${projectsTable.deleted} IS NULL`)
))
])
const totalUsers = Number(usersCount[0]?.count || 0)
const totalProjects = Number(projectsCount[0]?.count || 0)
const totalHours = Number(totalHoursResult[0]?.total || 0)
const pendingHours = Number(pendingHoursResult[0]?.total || 0)
const weightedGrants = Math.round(totalHours / 10 * 100) / 100
const pendingWeightedGrants = Math.round(pendingHours / 10 * 100) / 100
return {
totalUsers,
totalProjects,
totalHours: Math.round(totalHours * 10) / 10,
weightedGrants
weightedGrants,
pendingHours: Math.round(pendingHours * 10) / 10,
pendingWeightedGrants
}
})

View file

@ -1,7 +1,7 @@
<script lang="ts">
import { onMount } from 'svelte';
import { goto } from '$app/navigation';
import { Users, FolderKanban, Clock, Scale } from '@lucide/svelte';
import { Users, FolderKanban, Clock, Scale, Hourglass } from '@lucide/svelte';
import { getUser } from '$lib/auth-client';
import { API_URL } from '$lib/config';
@ -10,6 +10,8 @@
totalProjects: number;
totalHours: number;
weightedGrants: number;
pendingHours: number;
pendingWeightedGrants: number;
}
let stats = $state<Stats | null>(null);
@ -90,6 +92,33 @@
<p class="text-xs text-gray-400">total hours ÷ 10</p>
</div>
</div>
<div class="flex items-center gap-4 rounded-2xl border-4 border-yellow-500 bg-yellow-50 p-6">
<div
class="flex h-16 w-16 items-center justify-center rounded-full bg-yellow-500 text-white"
>
<Hourglass size={32} />
</div>
<div>
<p class="text-sm font-bold text-gray-500">pending hours</p>
<p class="text-4xl font-bold text-yellow-600">{stats.pendingHours.toLocaleString()}h</p>
</div>
</div>
<div class="flex items-center gap-4 rounded-2xl border-4 border-yellow-500 bg-yellow-50 p-6">
<div
class="flex h-16 w-16 items-center justify-center rounded-full bg-yellow-500 text-white"
>
<Scale size={32} />
</div>
<div>
<p class="text-sm font-bold text-gray-500">pending weighted grants</p>
<p class="text-4xl font-bold text-yellow-600">
{stats.pendingWeightedGrants.toLocaleString()}
</p>
<p class="text-xs text-gray-400">pending hours ÷ 10</p>
</div>
</div>
</div>
{/if}
</div>