chore: remove public community dashboard page

This commit is contained in:
2026-05-16 18:10:29 +08:00
parent 3363b9161d
commit 0ff27b613d
11 changed files with 365 additions and 706 deletions
@@ -1,106 +0,0 @@
"use client"
import { EChartWrapper, CHART_THEME } from "@/components/charts/EChartWrapper"
import type { EChartsOption } from "echarts"
interface BestRelease {
id: string
title: string
avg_fps: number | null
benchmark_count: number
}
function buildOption(games: BestRelease[]): EChartsOption {
const data = games.map((g) => ({
name: g.title,
value: [g.benchmark_count, Math.round((g.avg_fps ?? 0) * 10) / 10, g.benchmark_count],
itemStyle: {
color: {
type: "radial" as const,
x: 0.5,
y: 0.5,
r: 0.5,
colorStops: [
{ offset: 0, color: CHART_THEME.accent },
{ offset: 1, color: CHART_THEME.primary },
],
},
shadowBlur: 10,
shadowColor: CHART_THEME.primary + "40",
},
}))
return {
backgroundColor: CHART_THEME.bg,
tooltip: {
trigger: "item",
backgroundColor: "#1a1225",
borderColor: CHART_THEME.border,
textStyle: { color: CHART_THEME.text },
formatter: (params: unknown) => {
const p = params as { name: string; value: number[] }
const v = p.value
return `<div style="font-weight:600;margin-bottom:4px">${p.name}</div>
<div>Avg FPS: <b>${v[1]}</b></div>
<div>Benchmarks: <b>${v[2]}</b></div>`
},
},
grid: {
left: "3%",
right: "6%",
bottom: "10%",
top: "10%",
containLabel: true,
},
xAxis: {
name: "Benchmarks",
nameLocation: "middle",
nameGap: 24,
nameTextStyle: { color: CHART_THEME.textMuted, fontSize: 12 },
type: "value",
splitLine: { lineStyle: { color: CHART_THEME.border, type: "dashed" } },
axisLabel: { color: CHART_THEME.textMuted, fontSize: 11 },
axisLine: { lineStyle: { color: CHART_THEME.border } },
axisTick: { show: false },
},
yAxis: {
name: "Avg FPS",
nameTextStyle: { color: CHART_THEME.textMuted, fontSize: 12 },
type: "value",
splitLine: { lineStyle: { color: CHART_THEME.border, type: "dashed" } },
axisLabel: { color: CHART_THEME.textMuted, fontSize: 11 },
axisLine: { lineStyle: { color: CHART_THEME.border } },
axisTick: { show: false },
},
series: [
{
type: "scatter",
data,
symbolSize: (val: number[]) => Math.max(12, Math.min(40, val[2] * 3)),
label: {
show: true,
formatter: (p: unknown) => (p as { name: string }).name,
position: "top",
color: CHART_THEME.text,
fontSize: 10,
overflow: "truncate",
width: 100,
},
emphasis: {
scale: 1.5,
itemStyle: {
shadowBlur: 20,
shadowColor: CHART_THEME.accent + "60",
},
},
},
],
animationDuration: 800,
animationEasing: "cubicOut",
}
}
export function BestReleasesChart({ games }: { games: BestRelease[] }) {
if (!games.length) return null
return <EChartWrapper option={buildOption(games)} height={360} className="w-full" />
}
-117
View File
@@ -1,117 +0,0 @@
"use client"
import { TrendingUpIcon, SparklesIcon, BarChart3Icon } from "lucide-react"
import { TrendingGamesChart } from "./trending-games-chart"
import { BestReleasesChart } from "./best-releases-chart"
import { MostTestedChart } from "./most-tested-chart"
interface TrendingGame {
id: string
title: string
capsule_image: string | null
header_image: string | null
playability_status: string | null
benchmark_count: number
comment_count: number
upvote_count: number
activity_score: number
}
interface BestRelease {
id: string
title: string
capsule_image: string | null
header_image: string | null
release_date: string | null
created_at: string | null
playability_status: string | null
avg_fps: number | null
benchmark_count: number
}
interface MostTestedGame {
id: string
title: string
capsule_image: string | null
header_image: string | null
playability_status: string | null
benchmark_count: number
}
interface MostReportedGame {
id: string
title: string
capsule_image: string | null
header_image: string | null
report_count: number
}
interface DashboardClientProps {
trending: TrendingGame[]
bestNew: BestRelease[]
mostTested: MostTestedGame[]
mostReported: MostReportedGame[]
}
export function DashboardClient({
trending,
bestNew,
mostTested,
mostReported,
}: DashboardClientProps) {
return (
<main className="w-full px-4 md:px-8 lg:px-12 py-6 flex flex-col gap-8">
<header>
<h1 className="text-2xl md:text-3xl font-bold text-text">
Community Dashboard
</h1>
<p className="text-text/60 mt-1 text-sm md:text-base">
Real-time insights from the DeckyVault community trending games, top
performers, and activity highlights.
</p>
</header>
{/* Trending Games */}
<section className="rounded-xl border border-border bg-text/[0.03] p-4 md:p-6 flex flex-col gap-4">
<div className="flex items-center gap-2">
<TrendingUpIcon className="h-5 w-5 text-primary" />
<h2 className="text-lg md:text-xl font-semibold text-text">
Trending Games (7 days)
</h2>
</div>
<p className="text-text/60 text-sm">
Top games by community activity: benchmarks, comments, and upvotes.
</p>
<TrendingGamesChart games={trending} />
</section>
{/* Best New Releases */}
<section className="rounded-xl border border-border bg-text/[0.03] p-4 md:p-6 flex flex-col gap-4">
<div className="flex items-center gap-2">
<SparklesIcon className="h-5 w-5 text-accent" />
<h2 className="text-lg md:text-xl font-semibold text-text">
Best Performing New Releases
</h2>
</div>
<p className="text-text/60 text-sm">
Newly added games with the highest average FPS (minimum 3 benchmarks).
</p>
<BestReleasesChart games={bestNew} />
</section>
{/* Most Tested & Most Reported */}
<section className="rounded-xl border border-border bg-text/[0.03] p-4 md:p-6 flex flex-col gap-4">
<div className="flex items-center gap-2">
<BarChart3Icon className="h-5 w-5 text-info" />
<h2 className="text-lg md:text-xl font-semibold text-text">
Most Tested & Most Reported
</h2>
</div>
<p className="text-text/60 text-sm">
Games with the most benchmarks submitted and the most open reports.
</p>
<MostTestedChart mostTested={mostTested} mostReported={mostReported} />
</section>
</main>
)
}
-159
View File
@@ -1,159 +0,0 @@
"use client"
import { EChartWrapper, CHART_THEME } from "@/components/charts/EChartWrapper"
import type { EChartsOption } from "echarts"
interface MostTestedGame {
id: string
title: string
benchmark_count: number
}
interface MostReportedGame {
id: string
title: string
report_count: number
}
function buildOption(
tested: MostTestedGame[],
reported: MostReportedGame[],
): EChartsOption {
const testedTitles = tested.map((g) => g.title)
const testedCounts = tested.map((g) => g.benchmark_count)
const reportedTitles = reported.map((g) => g.title)
const reportedCounts = reported.map((g) => g.report_count)
return {
backgroundColor: CHART_THEME.bg,
tooltip: {
trigger: "axis",
axisPointer: { type: "shadow" },
backgroundColor: "#1a1225",
borderColor: CHART_THEME.border,
textStyle: { color: CHART_THEME.text },
},
legend: {
data: ["Most Tested", "Most Reported"],
textStyle: { color: CHART_THEME.textMuted },
bottom: 0,
},
grid: [
{
left: "3%",
right: "52%",
bottom: "14%",
top: "8%",
containLabel: true,
},
{
left: "52%",
right: "3%",
bottom: "14%",
top: "8%",
containLabel: true,
},
],
xAxis: [
{
type: "value",
gridIndex: 0,
splitLine: { lineStyle: { color: CHART_THEME.border, type: "dashed" } },
axisLabel: { color: CHART_THEME.textMuted, fontSize: 10 },
axisLine: { show: false },
axisTick: { show: false },
},
{
type: "value",
gridIndex: 1,
splitLine: { lineStyle: { color: CHART_THEME.border, type: "dashed" } },
axisLabel: { color: CHART_THEME.textMuted, fontSize: 10 },
axisLine: { show: false },
axisTick: { show: false },
},
],
yAxis: [
{
type: "category",
gridIndex: 0,
data: testedTitles,
axisLabel: { color: CHART_THEME.text, fontSize: 11, width: 120, overflow: "truncate" },
axisLine: { show: false },
axisTick: { show: false },
},
{
type: "category",
gridIndex: 1,
data: reportedTitles,
axisLabel: { color: CHART_THEME.text, fontSize: 11, width: 120, overflow: "truncate" },
axisLine: { show: false },
axisTick: { show: false },
},
],
series: [
{
name: "Most Tested",
type: "bar",
xAxisIndex: 0,
yAxisIndex: 0,
data: testedCounts,
barWidth: "55%",
itemStyle: {
borderRadius: [0, 4, 4, 0],
color: {
type: "linear",
x: 0,
y: 0,
x2: 1,
y2: 0,
colorStops: [
{ offset: 0, color: CHART_THEME.info },
{ offset: 1, color: CHART_THEME.success },
],
},
},
},
{
name: "Most Reported",
type: "bar",
xAxisIndex: 1,
yAxisIndex: 1,
data: reportedCounts,
barWidth: "55%",
itemStyle: {
borderRadius: [0, 4, 4, 0],
color: {
type: "linear",
x: 0,
y: 0,
x2: 1,
y2: 0,
colorStops: [
{ offset: 0, color: CHART_THEME.warning },
{ offset: 1, color: CHART_THEME.accent },
],
},
},
},
],
animationDuration: 800,
animationEasing: "cubicOut",
}
}
export function MostTestedChart({
mostTested,
mostReported,
}: {
mostTested: MostTestedGame[]
mostReported: MostReportedGame[]
}) {
if (!mostTested.length && !mostReported.length) return null
return (
<EChartWrapper
option={buildOption(mostTested, mostReported)}
height={420}
className="w-full"
/>
)
}
@@ -1,107 +0,0 @@
"use client"
import { EChartWrapper, CHART_THEME } from "@/components/charts/EChartWrapper"
import type { EChartsOption } from "echarts"
interface TrendingGame {
id: string
title: string
activity_score: number
benchmark_count: number
comment_count: number
upvote_count: number
}
function buildOption(games: TrendingGame[]): EChartsOption {
const sorted = [...games].reverse()
const titles = sorted.map((g) => g.title)
const scores = sorted.map((g) => g.activity_score)
const benchmarks = sorted.map((g) => g.benchmark_count)
return {
backgroundColor: CHART_THEME.bg,
tooltip: {
trigger: "axis",
axisPointer: { type: "shadow" },
backgroundColor: "#1a1225",
borderColor: CHART_THEME.border,
textStyle: { color: CHART_THEME.text },
formatter: (params: unknown) => {
const p = params as { dataIndex: number }[]
const idx = p[0].dataIndex
const g = sorted[idx]
return `<div style="font-weight:600;margin-bottom:4px">${g.title}</div>
<div>Activity Score: <b>${g.activity_score}</b></div>
<div style="font-size:12px;color:${CHART_THEME.textMuted};margin-top:4px">
Benchmarks: ${g.benchmark_count} · Comments: ${g.comment_count} · Upvotes: ${g.upvote_count}
</div>`
},
},
grid: {
left: "3%",
right: "4%",
bottom: "3%",
top: "3%",
containLabel: true,
},
xAxis: {
type: "value",
splitLine: { lineStyle: { color: CHART_THEME.border, type: "dashed" } },
axisLabel: { color: CHART_THEME.textMuted, fontSize: 11 },
axisLine: { show: false },
axisTick: { show: false },
},
yAxis: {
type: "category",
data: titles,
axisLabel: { color: CHART_THEME.text, fontSize: 12, width: 160, overflow: "truncate" },
axisLine: { show: false },
axisTick: { show: false },
},
series: [
{
name: "Activity Score",
type: "bar",
data: scores,
barWidth: "60%",
itemStyle: {
borderRadius: [0, 4, 4, 0],
color: {
type: "linear",
x: 0,
y: 0,
x2: 1,
y2: 0,
colorStops: [
{ offset: 0, color: CHART_THEME.secondary },
{ offset: 1, color: CHART_THEME.primary },
],
},
},
},
{
name: "Benchmarks",
type: "bar",
data: benchmarks,
barWidth: "60%",
barGap: "-100%",
itemStyle: {
borderRadius: [0, 4, 4, 0],
color: "transparent",
borderWidth: 1,
borderColor: CHART_THEME.accent,
},
emphasis: { disabled: true },
tooltip: { show: false },
silent: true,
},
],
animationDuration: 800,
animationEasing: "cubicOut",
}
}
export function TrendingGamesChart({ games }: { games: TrendingGame[] }) {
if (!games.length) return null
return <EChartWrapper option={buildOption(games)} height={360} className="w-full" />
}