import { createSignal, createResource, onMount, For, Show } from "solid-js"
const API_BASE = "http://localhost:3000/api/v1"
async function fetchJson(url: string, token: string) {
const res = await fetch(url, { headers: token ? { Authorization: `Bearer ${token}` } : {} })
return res.json()
}
export function AdminDashboard() {
const [token, setToken] = createSignal(localStorage.getItem("kirincode_token") || "")
const [email, setEmail] = createSignal("")
const [password, setPassword] = createSignal("")
const [loggedIn, setLoggedIn] = createSignal(!!token())
const [tab, setTab] = createSignal<"today" | "team" | "users" | "minute">("today")
// Login
async function login() {
const res = await fetch(API_BASE + "/auth/login", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ email: email(), password: password() }),
})
const data = await res.json()
if (data.token) {
localStorage.setItem("kirincode_token", data.token)
setToken(data.token)
setLoggedIn(true)
}
}
// Fetch data
const [todayData] = createResource(loggedIn, () => fetchJson(`${API_BASE}/admin/usage/today`, token()))
const [teamData] = createResource(loggedIn, () => fetchJson(`${API_BASE}/admin/usage/team`, token()))
const [usersData] = createResource(loggedIn, () => fetchJson(`${API_BASE}/admin/usage/users`, token()))
const [minuteData] = createResource(loggedIn, () => fetchJson(`${API_BASE}/admin/usage/minute`, token()))
// Refs for auto-refresh
onMount(() => {
const interval = setInterval(() => {
if (loggedIn()) {
fetchJson(`${API_BASE}/admin/usage/today`, token()).then(d => { /* trigger re-fetch */ })
}
}, 30000)
return () => clearInterval(interval)
})
if (!loggedIn()) {
return (
KirinCode Admin
setEmail(e.currentTarget.value)}
style={{ padding: "10px 14px", "border-radius": "8px", border: "1px solid #2c3e50", background: "#1a1a2e", color: "#ecf0f1", "font-size": "14px" }}
/>
setPassword(e.currentTarget.value)}
style={{ padding: "10px 14px", "border-radius": "8px", border: "1px solid #2c3e50", background: "#1a1a2e", color: "#ecf0f1", "font-size": "14px" }}
/>
)
}
return (
{/* Header */}
🦄 KirinCode Admin
{(["today", "team", "users", "minute"] as const).map(t => (
))}
{/* Content */}
{() => {
const d = todayData()?.data || {}
return (
)
}}
{() => (
Team Usage
| Day |
Provider |
Model |
Input |
Output |
Requests |
Cost |
{(row: any) => (
| {row.day} |
{row.provider} |
{row.model} |
{row.input_tokens?.toLocaleString()} |
{row.output_tokens?.toLocaleString()} |
{row.request_count} |
${row.total_cost?.toFixed(4)} |
)}
)}
{() => (
User Rankings
| User |
Email |
Input |
Output |
Requests |
Cost |
{(row: any) => (
| {row.display_name} |
{row.email} |
{row.input_tokens?.toLocaleString()} |
{row.output_tokens?.toLocaleString()} |
{row.request_count} |
${row.total_cost?.toFixed(4)} |
)}
)}
{() => (
Minute-Level Detail
| Time |
Provider |
Model |
Input |
Output |
Cost |
{(row: any) => (
| {row.minute} |
{row.provider} |
{row.model} |
{row.input_tokens?.toLocaleString()} |
{row.output_tokens?.toLocaleString()} |
${row.cost_usd?.toFixed(5)} |
)}
)}
)
}
function MetricCard(props: { label: string; value: string }) {
return (
{props.label}
{props.value}
)
}