mirror of
https://github.com/System-End/scraps.git
synced 2026-04-19 22:05:09 +00:00
cph
This commit is contained in:
parent
44048f3f03
commit
988b02c7d2
2 changed files with 110 additions and 3 deletions
|
|
@ -80,15 +80,45 @@ admin.get('/stats', async ({ headers, status }) => {
|
|||
const pendingWeightedGrants = Math.round(pendingHours / 10 * 100) / 100
|
||||
const inProgressWeightedGrants = Math.round(inProgressHours / 10 * 100) / 100
|
||||
|
||||
// Shop spending stats
|
||||
const [shopSpending, refinerySpending] = await Promise.all([
|
||||
db.select({
|
||||
totalSpent: sql<number>`COALESCE(SUM(${shopOrdersTable.totalPrice}), 0)`,
|
||||
purchaseSpent: sql<number>`COALESCE(SUM(CASE WHEN ${shopOrdersTable.orderType} = 'purchase' THEN ${shopOrdersTable.totalPrice} ELSE 0 END), 0)`,
|
||||
consolationSpent: sql<number>`COALESCE(SUM(CASE WHEN ${shopOrdersTable.orderType} = 'consolation' THEN ${shopOrdersTable.totalPrice} ELSE 0 END), 0)`,
|
||||
luckWinSpent: sql<number>`COALESCE(SUM(CASE WHEN ${shopOrdersTable.orderType} = 'luck_win' THEN ${shopOrdersTable.totalPrice} ELSE 0 END), 0)`
|
||||
}).from(shopOrdersTable),
|
||||
db.select({
|
||||
totalSpent: sql<number>`COALESCE(SUM(${refinerySpendingHistoryTable.cost}), 0)`
|
||||
}).from(refinerySpendingHistoryTable)
|
||||
])
|
||||
|
||||
const shopTotal = Number(shopSpending[0]?.totalSpent) || 0
|
||||
const shopPurchases = Number(shopSpending[0]?.purchaseSpent) || 0
|
||||
const shopConsolations = Number(shopSpending[0]?.consolationSpent) || 0
|
||||
const shopLuckWins = Number(shopSpending[0]?.luckWinSpent) || 0
|
||||
const refineryTotal = Number(refinerySpending[0]?.totalSpent) || 0
|
||||
const totalScrapsSpent = shopTotal + refineryTotal
|
||||
const roundedTotalHours = Math.round(totalHours * 10) / 10
|
||||
const costPerHour = roundedTotalHours > 0 ? Math.round(totalScrapsSpent / roundedTotalHours * 100) / 100 : 0
|
||||
|
||||
return {
|
||||
totalUsers,
|
||||
totalProjects,
|
||||
totalHours: Math.round(totalHours * 10) / 10,
|
||||
totalHours: roundedTotalHours,
|
||||
weightedGrants,
|
||||
pendingHours: Math.round(pendingHours * 10) / 10,
|
||||
pendingWeightedGrants,
|
||||
inProgressHours: Math.round(inProgressHours * 10) / 10,
|
||||
inProgressWeightedGrants
|
||||
inProgressWeightedGrants,
|
||||
shopStats: {
|
||||
totalScrapsSpent,
|
||||
shopPurchases,
|
||||
shopConsolations,
|
||||
shopLuckWins,
|
||||
refineryUpgrades: refineryTotal,
|
||||
costPerHour
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
|
|
|
|||
|
|
@ -1,11 +1,20 @@
|
|||
<script lang="ts">
|
||||
import { onMount } from 'svelte';
|
||||
import { goto } from '$app/navigation';
|
||||
import { Users, FolderKanban, Clock, Scale, Hourglass, ShieldAlert, Coins, XCircle, Download, RefreshCw } from '@lucide/svelte';
|
||||
import { Users, FolderKanban, Clock, Scale, Hourglass, ShieldAlert, Coins, XCircle, Download, RefreshCw, ShoppingCart, DollarSign } from '@lucide/svelte';
|
||||
import { getUser } from '$lib/auth-client';
|
||||
import { API_URL } from '$lib/config';
|
||||
import { t } from '$lib/i18n';
|
||||
|
||||
interface ShopStats {
|
||||
totalScrapsSpent: number;
|
||||
shopPurchases: number;
|
||||
shopConsolations: number;
|
||||
shopLuckWins: number;
|
||||
refineryUpgrades: number;
|
||||
costPerHour: number;
|
||||
}
|
||||
|
||||
interface Stats {
|
||||
totalUsers: number;
|
||||
totalProjects: number;
|
||||
|
|
@ -15,6 +24,7 @@
|
|||
pendingWeightedGrants: number;
|
||||
inProgressHours: number;
|
||||
inProgressWeightedGrants: number;
|
||||
shopStats?: ShopStats;
|
||||
}
|
||||
|
||||
interface PendingProject {
|
||||
|
|
@ -323,6 +333,73 @@
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{#if stats.shopStats}
|
||||
<h2 class="mt-10 mb-6 text-2xl font-bold">shop spending</h2>
|
||||
<div class="grid grid-cols-1 gap-6 md:grid-cols-2">
|
||||
<div class="flex items-center gap-4 rounded-2xl border-4 border-green-500 bg-green-50 p-6">
|
||||
<div class="flex h-16 w-16 items-center justify-center rounded-full bg-green-600 text-white">
|
||||
<DollarSign size={32} />
|
||||
</div>
|
||||
<div>
|
||||
<p class="text-sm font-bold text-gray-500">cost per hour</p>
|
||||
<p class="text-4xl font-bold text-green-700">{stats.shopStats.costPerHour.toLocaleString()}</p>
|
||||
<p class="text-xs text-gray-400">scraps spent ÷ shipped hours</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="flex items-center gap-4 rounded-2xl border-4 border-green-500 bg-green-50 p-6">
|
||||
<div class="flex h-16 w-16 items-center justify-center rounded-full bg-green-600 text-white">
|
||||
<ShoppingCart size={32} />
|
||||
</div>
|
||||
<div>
|
||||
<p class="text-sm font-bold text-gray-500">total scraps spent</p>
|
||||
<p class="text-4xl font-bold text-green-700">{stats.shopStats.totalScrapsSpent.toLocaleString()}</p>
|
||||
<p class="text-xs text-gray-400">shop + refinery</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="flex items-center gap-4 rounded-2xl border-4 border-black p-6">
|
||||
<div class="flex h-16 w-16 items-center justify-center rounded-full bg-black text-white">
|
||||
<Coins size={32} />
|
||||
</div>
|
||||
<div>
|
||||
<p class="text-sm font-bold text-gray-500">shop purchases</p>
|
||||
<p class="text-4xl font-bold">{stats.shopStats.shopPurchases.toLocaleString()}</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="flex items-center gap-4 rounded-2xl border-4 border-black p-6">
|
||||
<div class="flex h-16 w-16 items-center justify-center rounded-full bg-black text-white">
|
||||
<Coins size={32} />
|
||||
</div>
|
||||
<div>
|
||||
<p class="text-sm font-bold text-gray-500">consolation scraps</p>
|
||||
<p class="text-4xl font-bold">{stats.shopStats.shopConsolations.toLocaleString()}</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="flex items-center gap-4 rounded-2xl border-4 border-black p-6">
|
||||
<div class="flex h-16 w-16 items-center justify-center rounded-full bg-black text-white">
|
||||
<Coins size={32} />
|
||||
</div>
|
||||
<div>
|
||||
<p class="text-sm font-bold text-gray-500">luck wins</p>
|
||||
<p class="text-4xl font-bold">{stats.shopStats.shopLuckWins.toLocaleString()}</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="flex items-center gap-4 rounded-2xl border-4 border-black p-6">
|
||||
<div class="flex h-16 w-16 items-center justify-center rounded-full bg-black text-white">
|
||||
<Coins size={32} />
|
||||
</div>
|
||||
<div>
|
||||
<p class="text-sm font-bold text-gray-500">refinery upgrades</p>
|
||||
<p class="text-4xl font-bold">{stats.shopStats.refineryUpgrades.toLocaleString()}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue