Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions messages/en/dashboard.json
Original file line number Diff line number Diff line change
Expand Up @@ -450,6 +450,11 @@
"providerRanking": "Provider Rankings",
"providerCacheHitRateRanking": "Provider Cache Hit Rate",
"modelRanking": "Model Rankings",
"primaryUser": "Users",
"primaryProvider": "Providers",
"primaryModel": "Models",
"secondaryCost": "Cost",
"secondaryCacheHit": "Cache Hit Rate",
"dailyRanking": "Today",
"weeklyRanking": "This Week",
"monthlyRanking": "This Month",
Expand Down
5 changes: 5 additions & 0 deletions messages/ja/dashboard.json
Original file line number Diff line number Diff line change
Expand Up @@ -450,6 +450,11 @@
"providerRanking": "プロバイダーランキング",
"providerCacheHitRateRanking": "プロバイダーキャッシュ命中率",
"modelRanking": "モデルランキング",
"primaryUser": "ユーザー",
"primaryProvider": "プロバイダー",
"primaryModel": "モデル",
"secondaryCost": "コスト",
"secondaryCacheHit": "キャッシュ命中率",
"dailyRanking": "本日",
"weeklyRanking": "今週",
"monthlyRanking": "今月",
Expand Down
5 changes: 5 additions & 0 deletions messages/ru/dashboard.json
Original file line number Diff line number Diff line change
Expand Up @@ -450,6 +450,11 @@
"providerRanking": "Рейтинг поставщиков",
"providerCacheHitRateRanking": "Рейтинг по попаданиям в кэш",
"modelRanking": "Рейтинг моделей",
"primaryUser": "Пользователи",
"primaryProvider": "Поставщики",
"primaryModel": "Модели",
"secondaryCost": "По стоимости",
"secondaryCacheHit": "По попаданиям в кэш",
"dailyRanking": "Сегодня",
"weeklyRanking": "Эта неделя",
"monthlyRanking": "Этот месяц",
Expand Down
5 changes: 5 additions & 0 deletions messages/zh-CN/dashboard.json
Original file line number Diff line number Diff line change
Expand Up @@ -450,6 +450,11 @@
"providerRanking": "供应商排行",
"providerCacheHitRateRanking": "供应商缓存命中率排行",
"modelRanking": "模型排行",
"primaryUser": "用户",
"primaryProvider": "供应商",
"primaryModel": "模型",
"secondaryCost": "成本榜",
"secondaryCacheHit": "缓存命中榜",
"dailyRanking": "今日",
"weeklyRanking": "本周",
"monthlyRanking": "本月",
Expand Down
5 changes: 5 additions & 0 deletions messages/zh-TW/dashboard.json
Original file line number Diff line number Diff line change
Expand Up @@ -450,6 +450,11 @@
"providerRanking": "供應商排名",
"providerCacheHitRateRanking": "供應商快取命中率排行",
"modelRanking": "模型排名",
"primaryUser": "使用者",
"primaryProvider": "供應商",
"primaryModel": "模型榜",
"secondaryCost": "成本排名",
"secondaryCacheHit": "快取命中榜",
"dailyRanking": "今天",
"weeklyRanking": "本週",
"monthlyRanking": "當月",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
"use client";

import type { LeaderboardPrimaryTab } from "@/app/[locale]/dashboard/leaderboard/_components/leaderboard-tab-groups";
import { Tabs, TabsList, TabsTrigger } from "@/components/ui/tabs";

interface LeaderboardPrimaryTabLabels {
user: string;
provider: string;
model: string;
}

interface LeaderboardPrimaryTabsProps {
isAdmin: boolean;
activePrimaryTab: LeaderboardPrimaryTab;
onPrimaryChange: (tab: LeaderboardPrimaryTab) => void;
labels: LeaderboardPrimaryTabLabels;
}

export function LeaderboardPrimaryTabs({
isAdmin,
activePrimaryTab,
onPrimaryChange,
labels,
}: LeaderboardPrimaryTabsProps) {
return (
<Tabs
value={activePrimaryTab}
onValueChange={(value) => onPrimaryChange(value as LeaderboardPrimaryTab)}
>
<TabsList
data-testid="leaderboard-primary-tabs"
className={isAdmin ? "grid w-full grid-cols-3" : "w-full"}
>
<TabsTrigger data-testid="leaderboard-primary-tab-user" value="user">
{labels.user}
</TabsTrigger>
{isAdmin ? (
<TabsTrigger data-testid="leaderboard-primary-tab-provider" value="provider">
{labels.provider}
</TabsTrigger>
) : null}
{isAdmin ? (
<TabsTrigger data-testid="leaderboard-primary-tab-model" value="model">
{labels.model}
</TabsTrigger>
) : null}
</TabsList>
</Tabs>
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
"use client";

import type {
LeaderboardPrimaryTab,
LeaderboardSecondaryTab,
} from "@/app/[locale]/dashboard/leaderboard/_components/leaderboard-tab-groups";
import { Tabs, TabsList, TabsTrigger } from "@/components/ui/tabs";

interface LeaderboardSecondaryTabLabels {
cost: string;
cacheHit: string;
}

interface LeaderboardSecondaryTabsProps {
activePrimaryTab: LeaderboardPrimaryTab;
activeSecondaryTab: LeaderboardSecondaryTab | null;
onSecondaryChange: (tab: LeaderboardSecondaryTab) => void;
labels: LeaderboardSecondaryTabLabels;
}

export function LeaderboardSecondaryTabs({
activePrimaryTab,
activeSecondaryTab,
onSecondaryChange,
labels,
}: LeaderboardSecondaryTabsProps) {
if (activePrimaryTab === "model") {
return null;
}
Comment on lines +27 to +29
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Redundant model guard inside component

The activePrimaryTab === "model" early return is unreachable in practice: the parent already gates rendering with showSecondaryTabs = isAdmin && activePrimaryTab !== "model", so this component is never mounted when the primary tab is "model". The same applies to the ?? "cost" fallback on line 30 — activeSecondaryTab is only null for the "model" scope, which is already excluded by the parent guard. Both are harmless but add noise.

Prompt To Fix With AI
This is a comment left during a code review.
Path: src/app/[locale]/dashboard/leaderboard/_components/leaderboard-secondary-tabs.tsx
Line: 24-26

Comment:
**Redundant `model` guard inside component**

The `activePrimaryTab === "model"` early return is unreachable in practice: the parent already gates rendering with `showSecondaryTabs = isAdmin && activePrimaryTab !== "model"`, so this component is never mounted when the primary tab is `"model"`. The same applies to the `?? "cost"` fallback on line 30 — `activeSecondaryTab` is only `null` for the `"model"` scope, which is already excluded by the parent guard. Both are harmless but add noise.

How can I resolve this? If you propose a fix, please make it concise.


return (
<Tabs
value={activeSecondaryTab ?? "cost"}
onValueChange={(value) => onSecondaryChange(value as LeaderboardSecondaryTab)}
>
<TabsList data-testid="leaderboard-secondary-tabs" className="grid w-full grid-cols-2">
<TabsTrigger data-testid="leaderboard-secondary-tab-cost" value="cost">
{labels.cost}
</TabsTrigger>
<TabsTrigger data-testid="leaderboard-secondary-tab-cache-hit" value="cacheHit">
{labels.cacheHit}
</TabsTrigger>
</TabsList>
</Tabs>
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
export type LeaderboardLeafScope =
| "user"
| "userCacheHitRate"
| "provider"
| "providerCacheHitRate"
| "model";

export type LeaderboardPrimaryTab = "user" | "provider" | "model";
export type LeaderboardPrimaryTabWithSecondary = Exclude<LeaderboardPrimaryTab, "model">;
export type LeaderboardSecondaryTab = "cost" | "cacheHit";

export function normalizeScopeFromUrl(
scope: string | null | undefined,
isAdmin: boolean
): LeaderboardLeafScope {
if (scope === "user") {
return "user";
}

if (
isAdmin &&
(scope === "userCacheHitRate" ||
scope === "provider" ||
scope === "providerCacheHitRate" ||
scope === "model")
) {
return scope;
}

return "user";
}

export function getPrimaryTabFromScope(scope: LeaderboardLeafScope): LeaderboardPrimaryTab {
if (scope === "provider" || scope === "providerCacheHitRate") {
return "provider";
}

if (scope === "model") {
return "model";
}

return "user";
}

export function isUserFamilyScope(scope: LeaderboardLeafScope): boolean {
return getPrimaryTabFromScope(scope) === "user";
}

export function isProviderFamilyScope(scope: LeaderboardLeafScope): boolean {
return getPrimaryTabFromScope(scope) === "provider";
}

export function getSecondaryTabFromScope(
scope: LeaderboardLeafScope
): LeaderboardSecondaryTab | null {
if (scope === "model") {
return null;
}

return scope === "userCacheHitRate" || scope === "providerCacheHitRate" ? "cacheHit" : "cost";
}

export function getScopeForPrimaryTab(tab: LeaderboardPrimaryTab): LeaderboardLeafScope {
if (tab === "provider") {
return "provider";
}

if (tab === "model") {
return "model";
}

return "user";
}

export function getScopeForSecondaryTab(
primaryTab: LeaderboardPrimaryTabWithSecondary,
secondaryTab: LeaderboardSecondaryTab
): LeaderboardLeafScope {
if (primaryTab === "provider") {
return secondaryTab === "cacheHit" ? "providerCacheHitRate" : "provider";
}

return secondaryTab === "cacheHit" ? "userCacheHitRate" : "user";
}
Loading
Loading