fix(dashboard): stabilize usage tab loading and refresh behavior

Prevent repeated provider-limit refresh requests by guarding the bulk
refresh flow with a ref-backed lock instead of a stale callback
dependency.

Also avoid tying eval data loading to translation updates and replace the
fetch failure path with a static error so the effect runs predictably.
Refresh English cost dashboard copy to provide clearer labels and empty
state messaging.
This commit is contained in:
diegosouzapw
2026-04-25 22:45:08 -03:00
parent b9c20b2b06
commit 1e9e6d4349
3 changed files with 23 additions and 13 deletions

View File

@@ -353,7 +353,7 @@ export default function EvalsTab() {
try {
const response = await fetch("/api/evals");
if (!response.ok) {
throw new Error(t("notifyEvalRunFailed"));
throw new Error("Eval load failed");
}
const payload = (await response.json()) as EvalsDashboardPayload;
@@ -380,7 +380,8 @@ export default function EvalsTab() {
return () => {
isMounted = false;
};
}, [notify, t]);
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
useEffect(() => {
if (targetOptions.length === 0) return;

View File

@@ -238,8 +238,10 @@ export default function ProviderLimits() {
[fetchQuota]
);
const refreshingAllRef = useRef(false);
const refreshAll = useCallback(async () => {
if (refreshingAll) return;
if (refreshingAllRef.current) return;
refreshingAllRef.current = true;
setRefreshingAll(true);
try {
const response = await fetch("/api/usage/provider-limits", { method: "POST" });
@@ -256,9 +258,10 @@ export default function ProviderLimits() {
} catch (error) {
console.error("Error refreshing all:", error);
} finally {
refreshingAllRef.current = false;
setRefreshingAll(false);
}
}, [refreshingAll, applyCachedQuotaState, fetchConnections]);
}, [applyCachedQuotaState, fetchConnections]);
useEffect(() => {
const init = async () => {

View File

@@ -1784,29 +1784,35 @@
},
"costs": {
"title": "Costs",
"pageDescription": "Track spending, analyze trends, and manage your AI budget across all providers",
"overview": "Overview",
"budget": "Budget",
"totalCost": "Total Cost",
"breakdown": "Cost Breakdown",
"noData": "No cost data",
"byModel": "By Model",
"byProvider": "By Provider",
"spend30d": "Spend30D",
"range7d": "7 Days",
"range30d": "30 Days",
"range90d": "90 Days",
"rangeAll": "All Time",
"spend30d": "Spend 30D",
"activeModels": "Active Models",
"selectedWindow": "Selected Window",
"activeProviders": "Active Providers",
"overviewTitle": "Overview Title",
"spend7d": "Spend7D",
"avgCostPerRequest": "Avg Cost Per Request",
"noCostDataDescription": "No Cost Data Description",
"overviewTitle": "Cost Overview",
"spend7d": "Spend 7D",
"avgCostPerRequest": "Avg Cost / Request",
"noCostDataDescription": "Start making requests to see cost data appear here. Costs are tracked automatically for all providers.",
"spendToday": "Spend Today",
"overviewLoadFailed": "Overview Load Failed",
"overviewDescription": "Overview Description",
"overviewLoadFailed": "Failed to load cost overview",
"overviewDescription": "Real-time spending breakdown across all connected providers and models",
"providerShare": "Provider Share",
"topProviders": "Top Providers",
"costTrend": "Cost Trend",
"noCostDataTitle": "No Cost Data Title",
"noCostDataTitle": "No cost data yet",
"topModels": "Top Models",
"requestsInWindow": "Requests In Window"
"requestsInWindow": "Requests in Window"
},
"endpoint": {
"title": "API Endpoint",