chore: remove comments

This commit is contained in:
Austin Pickett
2026-04-28 12:28:08 -04:00
parent 0348a69c51
commit e1027134cd
12 changed files with 721 additions and 378 deletions

View File

@@ -1,13 +1,12 @@
import { useCallback, useEffect, useLayoutEffect, useState } from "react";
import {
BarChart3,
Brain,
Cpu,
RefreshCw,
TrendingUp,
} from "lucide-react";
import { BarChart3, Brain, Cpu, RefreshCw, TrendingUp } from "lucide-react";
import { api } from "@/lib/api";
import type { AnalyticsResponse, AnalyticsDailyEntry, AnalyticsModelEntry, AnalyticsSkillEntry } from "@/lib/api";
import type {
AnalyticsResponse,
AnalyticsDailyEntry,
AnalyticsModelEntry,
AnalyticsSkillEntry,
} from "@/lib/api";
import { timeAgo } from "@/lib/utils";
import { Button, Stats } from "@nous-research/ui";
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
@@ -43,16 +42,21 @@ function TokenBarChart({ daily }: { daily: AnalyticsDailyEntry[] }) {
const { t } = useI18n();
if (daily.length === 0) return null;
const maxTokens = Math.max(...daily.map((d) => d.input_tokens + d.output_tokens), 1);
const maxTokens = Math.max(
...daily.map((d) => d.input_tokens + d.output_tokens),
1,
);
return (
<Card>
<CardHeader>
<div className="flex items-center gap-2">
<BarChart3 className="h-5 w-5 text-muted-foreground" />
<CardTitle className="text-base">{t.analytics.dailyTokenUsage}</CardTitle>
<CardTitle className="text-base">
{t.analytics.dailyTokenUsage}
</CardTitle>
</div>
<div className="flex items-center gap-4 text-xs text-muted-foreground">
<div className="flex items-center gap-4 text-xs text-muted-foreground">
<div className="flex items-center gap-1.5">
<div className="h-2.5 w-2.5 bg-[#ffe6cb]" />
{t.analytics.input}
@@ -64,47 +68,63 @@ function TokenBarChart({ daily }: { daily: AnalyticsDailyEntry[] }) {
</div>
</CardHeader>
<CardContent>
<div className="flex items-end gap-[2px]" style={{ height: CHART_HEIGHT_PX }}>
<div
className="flex items-end gap-[2px]"
style={{ height: CHART_HEIGHT_PX }}
>
{daily.map((d) => {
const total = d.input_tokens + d.output_tokens;
const inputH = Math.round((d.input_tokens / maxTokens) * CHART_HEIGHT_PX);
const outputH = Math.round((d.output_tokens / maxTokens) * CHART_HEIGHT_PX);
const inputH = Math.round(
(d.input_tokens / maxTokens) * CHART_HEIGHT_PX,
);
const outputH = Math.round(
(d.output_tokens / maxTokens) * CHART_HEIGHT_PX,
);
return (
<div
key={d.day}
className="flex-1 min-w-0 group relative flex flex-col justify-end"
style={{ height: CHART_HEIGHT_PX }}
>
{/* Tooltip */}
<div className="absolute bottom-full left-1/2 -translate-x-1/2 mb-2 hidden group-hover:block z-10 pointer-events-none">
<div className="bg-card border border-border px-2.5 py-1.5 text-[10px] text-foreground shadow-lg whitespace-nowrap">
<div className="font-medium">{formatDate(d.day)}</div>
<div>{t.analytics.input}: {formatTokens(d.input_tokens)}</div>
<div>{t.analytics.output}: {formatTokens(d.output_tokens)}</div>
<div>{t.analytics.total}: {formatTokens(total)}</div>
<div>
{t.analytics.input}: {formatTokens(d.input_tokens)}
</div>
<div>
{t.analytics.output}: {formatTokens(d.output_tokens)}
</div>
<div>
{t.analytics.total}: {formatTokens(total)}
</div>
</div>
</div>
{/* Input bar */}
<div
className="w-full bg-[#ffe6cb]/70"
style={{ height: Math.max(inputH, total > 0 ? 1 : 0) }}
/>
{/* Output bar */}
<div
className="w-full bg-emerald-500/70"
style={{ height: Math.max(outputH, d.output_tokens > 0 ? 1 : 0) }}
style={{
height: Math.max(outputH, d.output_tokens > 0 ? 1 : 0),
}}
/>
</div>
);
})}
</div>
{/* X-axis labels */}
<div className="flex justify-between mt-2 text-[10px] text-muted-foreground">
<span>{daily.length > 0 ? formatDate(daily[0].day) : ""}</span>
{daily.length > 2 && (
<span>{formatDate(daily[Math.floor(daily.length / 2)].day)}</span>
)}
<span>{daily.length > 1 ? formatDate(daily[daily.length - 1].day) : ""}</span>
<span>
{daily.length > 1 ? formatDate(daily[daily.length - 1].day) : ""}
</span>
</div>
</CardContent>
</Card>
@@ -122,7 +142,9 @@ function DailyTable({ daily }: { daily: AnalyticsDailyEntry[] }) {
<CardHeader>
<div className="flex items-center gap-2">
<TrendingUp className="h-5 w-5 text-muted-foreground" />
<CardTitle className="text-base">{t.analytics.dailyBreakdown}</CardTitle>
<CardTitle className="text-base">
{t.analytics.dailyBreakdown}
</CardTitle>
</div>
</CardHeader>
<CardContent>
@@ -130,23 +152,42 @@ function DailyTable({ daily }: { daily: AnalyticsDailyEntry[] }) {
<table className="w-full text-sm">
<thead>
<tr className="border-b border-border text-muted-foreground text-xs">
<th className="text-left py-2 pr-4 font-medium">{t.analytics.date}</th>
<th className="text-right py-2 px-4 font-medium">{t.sessions.title}</th>
<th className="text-right py-2 px-4 font-medium">{t.analytics.input}</th>
<th className="text-right py-2 pl-4 font-medium">{t.analytics.output}</th>
<th className="text-left py-2 pr-4 font-medium">
{t.analytics.date}
</th>
<th className="text-right py-2 px-4 font-medium">
{t.sessions.title}
</th>
<th className="text-right py-2 px-4 font-medium">
{t.analytics.input}
</th>
<th className="text-right py-2 pl-4 font-medium">
{t.analytics.output}
</th>
</tr>
</thead>
<tbody>
{sorted.map((d) => {
return (
<tr key={d.day} className="border-b border-border/50 hover:bg-secondary/20 transition-colors">
<td className="py-2 pr-4 font-medium">{formatDate(d.day)}</td>
<td className="text-right py-2 px-4 text-muted-foreground">{d.sessions}</td>
<tr
key={d.day}
className="border-b border-border/50 hover:bg-secondary/20 transition-colors"
>
<td className="py-2 pr-4 font-medium">
{formatDate(d.day)}
</td>
<td className="text-right py-2 px-4 text-muted-foreground">
{d.sessions}
</td>
<td className="text-right py-2 px-4">
<span className="text-[#ffe6cb]">{formatTokens(d.input_tokens)}</span>
<span className="text-[#ffe6cb]">
{formatTokens(d.input_tokens)}
</span>
</td>
<td className="text-right py-2 pl-4">
<span className="text-emerald-400">{formatTokens(d.output_tokens)}</span>
<span className="text-emerald-400">
{formatTokens(d.output_tokens)}
</span>
</td>
</tr>
);
@@ -164,7 +205,8 @@ function ModelTable({ models }: { models: AnalyticsModelEntry[] }) {
if (models.length === 0) return null;
const sorted = [...models].sort(
(a, b) => b.input_tokens + b.output_tokens - (a.input_tokens + a.output_tokens),
(a, b) =>
b.input_tokens + b.output_tokens - (a.input_tokens + a.output_tokens),
);
return (
@@ -172,7 +214,9 @@ function ModelTable({ models }: { models: AnalyticsModelEntry[] }) {
<CardHeader>
<div className="flex items-center gap-2">
<Cpu className="h-5 w-5 text-muted-foreground" />
<CardTitle className="text-base">{t.analytics.perModelBreakdown}</CardTitle>
<CardTitle className="text-base">
{t.analytics.perModelBreakdown}
</CardTitle>
</div>
</CardHeader>
<CardContent>
@@ -180,22 +224,37 @@ function ModelTable({ models }: { models: AnalyticsModelEntry[] }) {
<table className="w-full text-sm">
<thead>
<tr className="border-b border-border text-muted-foreground text-xs">
<th className="text-left py-2 pr-4 font-medium">{t.analytics.model}</th>
<th className="text-right py-2 px-4 font-medium">{t.sessions.title}</th>
<th className="text-right py-2 pl-4 font-medium">{t.analytics.tokens}</th>
<th className="text-left py-2 pr-4 font-medium">
{t.analytics.model}
</th>
<th className="text-right py-2 px-4 font-medium">
{t.sessions.title}
</th>
<th className="text-right py-2 pl-4 font-medium">
{t.analytics.tokens}
</th>
</tr>
</thead>
<tbody>
{sorted.map((m) => (
<tr key={m.model} className="border-b border-border/50 hover:bg-secondary/20 transition-colors">
<tr
key={m.model}
className="border-b border-border/50 hover:bg-secondary/20 transition-colors"
>
<td className="py-2 pr-4">
<span className="font-mono-ui text-xs">{m.model}</span>
</td>
<td className="text-right py-2 px-4 text-muted-foreground">{m.sessions}</td>
<td className="text-right py-2 px-4 text-muted-foreground">
{m.sessions}
</td>
<td className="text-right py-2 pl-4">
<span className="text-[#ffe6cb]">{formatTokens(m.input_tokens)}</span>
<span className="text-[#ffe6cb]">
{formatTokens(m.input_tokens)}
</span>
{" / "}
<span className="text-emerald-400">{formatTokens(m.output_tokens)}</span>
<span className="text-emerald-400">
{formatTokens(m.output_tokens)}
</span>
</td>
</tr>
))}
@@ -224,21 +283,38 @@ function SkillTable({ skills }: { skills: AnalyticsSkillEntry[] }) {
<table className="w-full text-sm">
<thead>
<tr className="border-b border-border text-muted-foreground text-xs">
<th className="text-left py-2 pr-4 font-medium">{t.analytics.skill}</th>
<th className="text-right py-2 px-4 font-medium">{t.analytics.loads}</th>
<th className="text-right py-2 px-4 font-medium">{t.analytics.edits}</th>
<th className="text-right py-2 px-4 font-medium">{t.analytics.total}</th>
<th className="text-right py-2 pl-4 font-medium">{t.analytics.lastUsed}</th>
<th className="text-left py-2 pr-4 font-medium">
{t.analytics.skill}
</th>
<th className="text-right py-2 px-4 font-medium">
{t.analytics.loads}
</th>
<th className="text-right py-2 px-4 font-medium">
{t.analytics.edits}
</th>
<th className="text-right py-2 px-4 font-medium">
{t.analytics.total}
</th>
<th className="text-right py-2 pl-4 font-medium">
{t.analytics.lastUsed}
</th>
</tr>
</thead>
<tbody>
{skills.map((skill) => (
<tr key={skill.skill} className="border-b border-border/50 hover:bg-secondary/20 transition-colors">
<tr
key={skill.skill}
className="border-b border-border/50 hover:bg-secondary/20 transition-colors"
>
<td className="py-2 pr-4">
<span className="font-mono-ui text-xs">{skill.skill}</span>
</td>
<td className="text-right py-2 px-4 text-muted-foreground">{skill.view_count}</td>
<td className="text-right py-2 px-4 text-muted-foreground">{skill.manage_count}</td>
<td className="text-right py-2 px-4 text-muted-foreground">
{skill.view_count}
</td>
<td className="text-right py-2 px-4 text-muted-foreground">
{skill.manage_count}
</td>
<td className="text-right py-2 px-4">{skill.total_count}</td>
<td className="text-right py-2 pl-4 text-muted-foreground">
{skill.last_used_at ? timeAgo(skill.last_used_at) : "—"}
@@ -338,7 +414,6 @@ export default function AnalyticsPage() {
{data && (
<>
{/* Summary stats + bar chart side-by-side on lg+ */}
<div className="grid gap-6 lg:grid-cols-2">
<Card>
<CardContent className="py-6">
@@ -377,24 +452,28 @@ export default function AnalyticsPage() {
<TokenBarChart daily={data.daily} />
</div>
{/* Tables */}
<DailyTable daily={data.daily} />
<ModelTable models={data.by_model} />
<SkillTable skills={data.skills.top_skills} />
</>
)}
{data && data.daily.length === 0 && data.by_model.length === 0 && data.skills.top_skills.length === 0 && (
<Card>
<CardContent className="py-12">
<div className="flex flex-col items-center text-muted-foreground">
<BarChart3 className="h-8 w-8 mb-3 opacity-40" />
<p className="text-sm font-medium">{t.analytics.noUsageData}</p>
<p className="text-xs mt-1 text-muted-foreground/60">{t.analytics.startSession}</p>
</div>
</CardContent>
</Card>
)}
{data &&
data.daily.length === 0 &&
data.by_model.length === 0 &&
data.skills.top_skills.length === 0 && (
<Card>
<CardContent className="py-12">
<div className="flex flex-col items-center text-muted-foreground">
<BarChart3 className="h-8 w-8 mb-3 opacity-40" />
<p className="text-sm font-medium">{t.analytics.noUsageData}</p>
<p className="text-xs mt-1 text-muted-foreground/60">
{t.analytics.startSession}
</p>
</div>
</CardContent>
</Card>
)}
<PluginSlot name="analytics:bottom" />
</div>
);