chore: remove public community dashboard page
This commit is contained in:
@@ -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" />
|
||||
}
|
||||
@@ -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>
|
||||
)
|
||||
}
|
||||
@@ -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" />
|
||||
}
|
||||
Reference in New Issue
Block a user