style(admin): 비용 표시 제거 — 사내 LLM 은 단가 없어 항상 0. 토큰·응답시간만
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Fable 5.1
parent
d4a5f20787
commit
9fc93ffbce
@@ -91,7 +91,6 @@ describe("AdminStatsPage", () => {
|
||||
asUser("ADMIN")
|
||||
mount()
|
||||
expect(await screen.findByText("1,500")).toBeTruthy() // 총 토큰
|
||||
expect(screen.getByText("$0.1234")).toBeTruthy()
|
||||
expect(screen.getByText("2.5s")).toBeTruthy()
|
||||
expect(screen.getByText("김개발")).toBeTruthy()
|
||||
expect(client.apiGet).toHaveBeenCalledTimes(1)
|
||||
|
||||
@@ -9,7 +9,6 @@ import { ApiError } from "@/lib/api/errors"
|
||||
import { useAdminStats } from "../api/admin.api"
|
||||
|
||||
const fmtInt = (n: number) => n.toLocaleString("ko-KR")
|
||||
const fmtUsd = (n: number) => `$${n.toFixed(n < 1 ? 4 : 2)}`
|
||||
const fmtSec = (ms: number | null) => (ms === null ? "–" : `${(ms / 1000).toFixed(1)}s`)
|
||||
const isoDay = (d: Date) => d.toISOString().slice(0, 10)
|
||||
|
||||
@@ -20,7 +19,8 @@ const PRESETS: { label: string; days: number }[] = [
|
||||
{ label: "90일", days: 90 },
|
||||
]
|
||||
|
||||
/** 관리자 대시보드 — 총 토큰·비용·응답시간 + 사용자별·일별. 서버는 ChatMessage 집계만(새로 모으는 것 없음). */
|
||||
/** 관리자 대시보드 — 총 토큰·응답시간 + 사용자별·일별. 서버는 ChatMessage 집계만(새로 모으는 것 없음).
|
||||
* 비용은 안 보여줌 — 사내 LLM(FabriX) 은 단가가 없어 OpenCode 가 0 으로 줌. 단가 정해지면 그때 카드 추가. */
|
||||
export default function AdminStatsPage() {
|
||||
const navigate = useNavigate()
|
||||
const isAdmin = useAuthStore((s) => s.user?.role === "ADMIN")
|
||||
@@ -86,7 +86,7 @@ export default function AdminStatsPage() {
|
||||
{t && (
|
||||
<>
|
||||
{/* 요약 카드 4개 */}
|
||||
<div className="grid grid-cols-2 gap-2 sm:grid-cols-4">
|
||||
<div className="grid grid-cols-3 gap-2">
|
||||
<Stat
|
||||
label="요청"
|
||||
value={fmtInt(t.requests)}
|
||||
@@ -97,7 +97,6 @@ export default function AdminStatsPage() {
|
||||
value={fmtInt(t.totalTokens)}
|
||||
sub={`입력 ${fmtInt(t.inputTokens)} · 출력 ${fmtInt(t.outputTokens)}`}
|
||||
/>
|
||||
<Stat label="비용" value={fmtUsd(t.costUsd)} sub="OpenCode 집계 기준" />
|
||||
<Stat label="평균 응답" value={fmtSec(t.avgElapsedMs)} sub="첫 요청→완료" />
|
||||
</div>
|
||||
|
||||
@@ -115,7 +114,7 @@ export default function AdminStatsPage() {
|
||||
{data.byDay.map((d) => (
|
||||
<div
|
||||
key={d.day}
|
||||
title={`${d.day}: ${fmtInt(d.totalTokens)} 토큰 · ${d.requests}건 · ${fmtUsd(d.costUsd)}`}
|
||||
title={`${d.day}: ${fmtInt(d.totalTokens)} 토큰 · ${d.requests}건`}
|
||||
className="bg-primary/80 hover:bg-primary min-w-[4px] flex-1 rounded-sm transition-colors"
|
||||
style={{ height: `${Math.max(2, (d.totalTokens / maxDayTokens) * 100)}%` }}
|
||||
/>
|
||||
@@ -133,14 +132,13 @@ export default function AdminStatsPage() {
|
||||
<th className="px-3 py-2 text-right font-semibold">요청</th>
|
||||
<th className="px-3 py-2 text-right font-semibold">세션</th>
|
||||
<th className="px-3 py-2 text-right font-semibold">토큰</th>
|
||||
<th className="px-3 py-2 text-right font-semibold">비용</th>
|
||||
<th className="px-3 py-2 text-right font-semibold">평균 응답</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody className="divide-border/70 divide-y">
|
||||
{data.byUser.length === 0 && (
|
||||
<tr>
|
||||
<td colSpan={6} className="text-muted-foreground py-6 text-center text-xs">
|
||||
<td colSpan={5} className="text-muted-foreground py-6 text-center text-xs">
|
||||
기간 내 사용자 없음
|
||||
</td>
|
||||
</tr>
|
||||
@@ -154,7 +152,6 @@ export default function AdminStatsPage() {
|
||||
<td className="px-3 py-2 text-right tabular-nums">{fmtInt(u.requests)}</td>
|
||||
<td className="px-3 py-2 text-right tabular-nums">{fmtInt(u.sessions)}</td>
|
||||
<td className="px-3 py-2 text-right tabular-nums">{fmtInt(u.totalTokens)}</td>
|
||||
<td className="px-3 py-2 text-right tabular-nums">{fmtUsd(u.costUsd)}</td>
|
||||
<td className="px-3 py-2 text-right tabular-nums">{fmtSec(u.avgElapsedMs)}</td>
|
||||
</tr>
|
||||
))}
|
||||
|
||||
Reference in New Issue
Block a user