+
)}
-
+
+
+
{sendError && (
-
+
{sendError}
)}
diff --git a/ui/web/src/pages/usage/components/distribution-donut.tsx b/ui/web/src/pages/usage/components/distribution-donut.tsx
index 6916a6fa..2b21fccd 100644
--- a/ui/web/src/pages/usage/components/distribution-donut.tsx
+++ b/ui/web/src/pages/usage/components/distribution-donut.tsx
@@ -35,7 +35,6 @@ export function DistributionDonut({
metric = "request_count",
}: DistributionDonutProps) {
const { t } = useTranslation("usage");
- const isEmpty = !loading && data.length === 0;
const sorted = [...data].sort((a, b) => b[metric] - a[metric]);
const top = sorted.slice(0, MAX_SLICES);
@@ -49,8 +48,10 @@ export function DistributionDonut({
}
const total = slices.reduce((sum, s) => sum + s.value, 0);
+ const isEmpty = !loading && (data.length === 0 || total === 0);
- const handleClick = (entry: PieSectorDataItem) => {
+ const handleClick = (entry: PieSectorDataItem | null | undefined) => {
+ if (!entry) return;
const name = entry.name as string | undefined;
if (!name || name === t("analytics.distribution.other")) return;
onSliceClick?.(name);
@@ -66,10 +67,11 @@ export function DistributionDonut({
cy="45%"
innerRadius={55}
outerRadius={85}
- paddingAngle={2}
+ paddingAngle={slices.length > 1 ? 2 : 0}
dataKey="value"
onClick={handleClick}
style={{ cursor: onSliceClick ? "pointer" : "default" }}
+ isAnimationActive={false}
label={false}
>
{slices.map((entry, idx) => (
@@ -90,9 +92,13 @@ export function DistributionDonut({
{
- const v = typeof value === "number" ? value : Number(value) || 0;
- const pct = total > 0 ? ((v / total) * 100).toFixed(1) : "0";
- return [`${v.toLocaleString()} (${pct}%)`, String(name)];
+ try {
+ const v = typeof value === "number" ? value : Number(value) || 0;
+ const pct = total > 0 ? ((v / total) * 100).toFixed(1) : "0";
+ return [`${v.toLocaleString()} (${pct}%)`, String(name)];
+ } catch {
+ return [String(value), String(name)];
+ }
}}
/>
);
}
diff --git a/ui/web/src/pages/usage/components/duration-chart.tsx b/ui/web/src/pages/usage/components/duration-chart.tsx
index b8026eb4..4179243f 100644
--- a/ui/web/src/pages/usage/components/duration-chart.tsx
+++ b/ui/web/src/pages/usage/components/duration-chart.tsx
@@ -54,6 +54,7 @@ export function DurationChart({ data, loading, granularity }: DurationChartProps
name={t("analytics.durationChart.avgDuration")}
fill="#8b5cf6"
radius={[2, 2, 0, 0]}
+ isAnimationActive={false}
/>
diff --git a/ui/web/src/pages/usage/components/knowledge-chart.tsx b/ui/web/src/pages/usage/components/knowledge-chart.tsx
index 49d7f22d..e09148cb 100644
--- a/ui/web/src/pages/usage/components/knowledge-chart.tsx
+++ b/ui/web/src/pages/usage/components/knowledge-chart.tsx
@@ -47,10 +47,10 @@ export function KnowledgeChart({ data, loading, granularity }: KnowledgeChartPro
-
-
-
-
+
+
+
+
diff --git a/ui/web/src/pages/usage/components/request-volume-chart.tsx b/ui/web/src/pages/usage/components/request-volume-chart.tsx
index 2d0b1d73..fe9ec15e 100644
--- a/ui/web/src/pages/usage/components/request-volume-chart.tsx
+++ b/ui/web/src/pages/usage/components/request-volume-chart.tsx
@@ -57,6 +57,7 @@ export function RequestVolumeChart({ data, loading, granularity }: RequestVolume
name={t("analytics.requestChart.requests")}
fill="#3b82f6"
radius={[2, 2, 0, 0]}
+ isAnimationActive={false}
/>
diff --git a/ui/web/src/pages/usage/components/token-area-chart.tsx b/ui/web/src/pages/usage/components/token-area-chart.tsx
index 3483df2d..ac589f16 100644
--- a/ui/web/src/pages/usage/components/token-area-chart.tsx
+++ b/ui/web/src/pages/usage/components/token-area-chart.tsx
@@ -38,7 +38,7 @@ export function TokenAreaChart({ data, loading, granularity }: TokenAreaChartPro
emptyText={t("analytics.noData")}
>
-
+
@@ -64,6 +64,7 @@ export function TokenAreaChart({ data, loading, granularity }: TokenAreaChartPro
stroke="#3b82f6"
fill="url(#inputGrad)"
strokeWidth={2}
+ isAnimationActive={false}
stackId="tokens"
/>
{hasCache && (
@@ -83,6 +85,7 @@ export function TokenAreaChart({ data, loading, granularity }: TokenAreaChartPro
stroke="#06b6d4"
fill="none"
strokeWidth={1.5}
+ isAnimationActive={false}
strokeDasharray="4 2"
/>
)}
diff --git a/ui/web/src/pages/usage/usage-page.tsx b/ui/web/src/pages/usage/usage-page.tsx
index 079ca890..8a96dbba 100644
--- a/ui/web/src/pages/usage/usage-page.tsx
+++ b/ui/web/src/pages/usage/usage-page.tsx
@@ -100,22 +100,36 @@ function AnalyticsDashboard() {