Skip to content

Commit e1ef01f

Browse files
committed
fix
1 parent 5fc130d commit e1ef01f

File tree

2 files changed

+71
-134
lines changed

2 files changed

+71
-134
lines changed
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
interface LeaderboardEntry {
2+
name: string;
3+
githubUrl: string;
4+
packageName: string;
5+
score: number;
6+
errorCount: number;
7+
warningCount: number;
8+
fileCount: number;
9+
}
10+
11+
const buildShareUrl = (entry: LeaderboardEntry): string => {
12+
const searchParams = new URLSearchParams({
13+
p: entry.packageName,
14+
s: String(entry.score),
15+
e: String(entry.errorCount),
16+
w: String(entry.warningCount),
17+
f: String(entry.fileCount),
18+
});
19+
return `/share?${searchParams.toString()}`;
20+
};
21+
22+
const RAW_ENTRIES: LeaderboardEntry[] = [
23+
{ name: "tldraw", githubUrl: "https://github.com/tldraw/tldraw", packageName: "tldraw", score: 84, errorCount: 98, warningCount: 139, fileCount: 40 },
24+
{ name: "excalidraw", githubUrl: "https://github.com/excalidraw/excalidraw", packageName: "@excalidraw/excalidraw", score: 84, errorCount: 2, warningCount: 196, fileCount: 80 },
25+
{ name: "twenty", githubUrl: "https://github.com/twentyhq/twenty", packageName: "twenty-front", score: 78, errorCount: 99, warningCount: 293, fileCount: 268 },
26+
{ name: "plane", githubUrl: "https://github.com/makeplane/plane", packageName: "web", score: 78, errorCount: 7, warningCount: 525, fileCount: 292 },
27+
{ name: "formbricks", githubUrl: "https://github.com/formbricks/formbricks", packageName: "@formbricks/web", score: 75, errorCount: 15, warningCount: 389, fileCount: 242 },
28+
{ name: "posthog", githubUrl: "https://github.com/PostHog/posthog", packageName: "@posthog/frontend", score: 72, errorCount: 82, warningCount: 1177, fileCount: 585 },
29+
{ name: "supabase", githubUrl: "https://github.com/supabase/supabase", packageName: "studio", score: 69, errorCount: 74, warningCount: 1087, fileCount: 566 },
30+
{ name: "onlook", githubUrl: "https://github.com/onlook-dev/onlook", packageName: "@onlook/web-client", score: 69, errorCount: 64, warningCount: 418, fileCount: 178 },
31+
{ name: "payload", githubUrl: "https://github.com/payloadcms/payload", packageName: "@payloadcms/ui", score: 68, errorCount: 139, warningCount: 408, fileCount: 298 },
32+
{ name: "sentry", githubUrl: "https://github.com/getsentry/sentry", packageName: "sentry", score: 64, errorCount: 94, warningCount: 1345, fileCount: 818 },
33+
{ name: "cal.com", githubUrl: "https://github.com/calcom/cal.com", packageName: "@calcom/web", score: 63, errorCount: 31, warningCount: 558, fileCount: 311 },
34+
{ name: "dub", githubUrl: "https://github.com/dubinc/dub", packageName: "web", score: 62, errorCount: 52, warningCount: 966, fileCount: 457 },
35+
];
36+
37+
export interface ResolvedLeaderboardEntry extends LeaderboardEntry {
38+
shareUrl: string;
39+
}
40+
41+
export const LEADERBOARD_ENTRIES: ResolvedLeaderboardEntry[] = RAW_ENTRIES
42+
.sort((entryA, entryB) => entryB.score - entryA.score)
43+
.map((entry) => ({ ...entry, shareUrl: buildShareUrl(entry) }));

packages/website/src/app/leaderboard/page.tsx

Lines changed: 28 additions & 134 deletions
Original file line numberDiff line numberDiff line change
@@ -1,132 +1,14 @@
11
import type { Metadata } from "next";
22
import Link from "next/link";
3+
import { LEADERBOARD_ENTRIES, type ResolvedLeaderboardEntry } from "./leaderboard-entries";
34

45
const PERFECT_SCORE = 100;
56
const SCORE_GOOD_THRESHOLD = 75;
67
const SCORE_OK_THRESHOLD = 50;
78
const SCORE_BAR_WIDTH = 20;
89
const COMMAND = "npx -y react-doctor@latest .";
9-
10-
interface LeaderboardEntry {
11-
name: string;
12-
githubUrl: string;
13-
score: number;
14-
errorCount: number;
15-
warningCount: number;
16-
fileCount: number;
17-
shareUrl: string;
18-
}
19-
20-
const LEADERBOARD_ENTRIES: LeaderboardEntry[] = [
21-
{
22-
name: "tldraw",
23-
githubUrl: "https://github.com/tldraw/tldraw",
24-
score: 84,
25-
errorCount: 98,
26-
warningCount: 139,
27-
fileCount: 40,
28-
shareUrl: "/share?p=tldraw&s=84&e=98&w=139&f=40",
29-
},
30-
{
31-
name: "excalidraw",
32-
githubUrl: "https://github.com/excalidraw/excalidraw",
33-
score: 84,
34-
errorCount: 2,
35-
warningCount: 196,
36-
fileCount: 80,
37-
shareUrl: "/share?p=%40excalidraw%2Fexcalidraw&s=84&e=2&w=196&f=80",
38-
},
39-
{
40-
name: "twenty",
41-
githubUrl: "https://github.com/twentyhq/twenty",
42-
score: 78,
43-
errorCount: 99,
44-
warningCount: 293,
45-
fileCount: 268,
46-
shareUrl: "/share?p=twenty-front&s=78&e=99&w=293&f=268",
47-
},
48-
{
49-
name: "plane",
50-
githubUrl: "https://github.com/makeplane/plane",
51-
score: 78,
52-
errorCount: 7,
53-
warningCount: 525,
54-
fileCount: 292,
55-
shareUrl: "/share?p=web&s=78&e=7&w=525&f=292",
56-
},
57-
{
58-
name: "formbricks",
59-
githubUrl: "https://github.com/formbricks/formbricks",
60-
score: 75,
61-
errorCount: 15,
62-
warningCount: 389,
63-
fileCount: 242,
64-
shareUrl: "/share?p=%40formbricks%2Fweb&s=75&e=15&w=389&f=242",
65-
},
66-
{
67-
name: "posthog",
68-
githubUrl: "https://github.com/PostHog/posthog",
69-
score: 72,
70-
errorCount: 82,
71-
warningCount: 1177,
72-
fileCount: 585,
73-
shareUrl: "/share?p=%40posthog%2Ffrontend&s=72&e=82&w=1177&f=585",
74-
},
75-
{
76-
name: "supabase",
77-
githubUrl: "https://github.com/supabase/supabase",
78-
score: 69,
79-
errorCount: 74,
80-
warningCount: 1087,
81-
fileCount: 566,
82-
shareUrl: "/share?p=studio&s=69&e=74&w=1087&f=566",
83-
},
84-
{
85-
name: "onlook",
86-
githubUrl: "https://github.com/onlook-dev/onlook",
87-
score: 69,
88-
errorCount: 64,
89-
warningCount: 418,
90-
fileCount: 178,
91-
shareUrl: "/share?p=%40onlook%2Fweb-client&s=69&e=64&w=418&f=178",
92-
},
93-
{
94-
name: "payload",
95-
githubUrl: "https://github.com/payloadcms/payload",
96-
score: 68,
97-
errorCount: 139,
98-
warningCount: 408,
99-
fileCount: 298,
100-
shareUrl: "/share?p=%40payloadcms%2Fui&s=68&e=139&w=408&f=298",
101-
},
102-
{
103-
name: "sentry",
104-
githubUrl: "https://github.com/getsentry/sentry",
105-
score: 64,
106-
errorCount: 94,
107-
warningCount: 1345,
108-
fileCount: 818,
109-
shareUrl: "/share?p=sentry&s=64&e=94&w=1345&f=818",
110-
},
111-
{
112-
name: "cal.com",
113-
githubUrl: "https://github.com/calcom/cal.com",
114-
score: 63,
115-
errorCount: 31,
116-
warningCount: 558,
117-
fileCount: 311,
118-
shareUrl: "/share?p=%40calcom%2Fweb&s=63&e=31&w=558&f=311",
119-
},
120-
{
121-
name: "dub",
122-
githubUrl: "https://github.com/dubinc/dub",
123-
score: 62,
124-
errorCount: 52,
125-
warningCount: 966,
126-
fileCount: 457,
127-
shareUrl: "/share?p=web&s=62&e=52&w=966&f=457",
128-
},
129-
];
10+
const CONTRIBUTE_URL =
11+
"https://github.com/millionco/react-doctor/edit/main/packages/website/src/app/leaderboard/leaderboard-entries.ts";
13012

13113
const getScoreColorClass = (score: number): string => {
13214
if (score >= SCORE_GOOD_THRESHOLD) return "text-green-400";
@@ -140,8 +22,6 @@ const getDoctorFace = (score: number): [string, string] => {
14022
return ["x x", " ▽ "];
14123
};
14224

143-
const MAX_NAME_LENGTH = 12;
144-
14525
const ScoreBar = ({ score }: { score: number }) => {
14626
const filledCount = Math.round((score / PERFECT_SCORE) * SCORE_BAR_WIDTH);
14727
const emptyCount = SCORE_BAR_WIDTH - filledCount;
@@ -155,31 +35,27 @@ const ScoreBar = ({ score }: { score: number }) => {
15535
);
15636
};
15737

158-
const LeaderboardRow = ({ entry, rank }: { entry: LeaderboardEntry; rank: number }) => {
38+
const LeaderboardRow = ({ entry, rank }: { entry: ResolvedLeaderboardEntry; rank: number }) => {
15939
const colorClass = getScoreColorClass(entry.score);
160-
const paddedName = entry.name.padEnd(MAX_NAME_LENGTH);
16140

16241
return (
163-
<div className="group flex items-center gap-2 border-b border-white/5 py-2 transition-colors hover:bg-white/2 sm:gap-4 sm:py-2.5">
164-
<span className="w-6 shrink-0 text-right text-neutral-600 sm:w-8">{rank}</span>
42+
<div className="group grid items-center border-b border-white/5 py-2 transition-colors hover:bg-white/2 sm:py-2.5 grid-cols-[2rem_1fr_auto] sm:grid-cols-[2.5rem_7rem_1fr_auto]">
43+
<span className="text-right text-neutral-600">{rank}</span>
16544

16645
<a
16746
href={entry.githubUrl}
16847
target="_blank"
16948
rel="noreferrer"
170-
className="shrink-0 text-white transition-colors hover:text-blue-400"
49+
className="ml-2 truncate text-white transition-colors hover:text-blue-400 sm:ml-4"
17150
>
172-
<span className="sm:hidden">
173-
{entry.name.length > 10 ? `${entry.name.slice(0, 9)}…` : entry.name}
174-
</span>
175-
<span className="hidden sm:inline">{paddedName}</span>
51+
{entry.name}
17652
</a>
17753

178-
<span className="hidden flex-1 sm:inline">
54+
<span className="hidden sm:inline">
17955
<ScoreBar score={entry.score} />
18056
</span>
18157

182-
<Link href={entry.shareUrl} className="ml-auto shrink-0 transition-colors hover:underline">
58+
<Link href={entry.shareUrl} className="ml-4 text-right transition-colors hover:underline">
18359
<span className={`${colorClass} font-medium`}>{entry.score}</span>
18460
<span className="text-neutral-600">/{PERFECT_SCORE}</span>
18561
</Link>
@@ -230,6 +106,24 @@ const LeaderboardPage = () => {
230106
<div className="mt-2">
231107
<span className="border border-white/20 px-3 py-1.5 text-white">{COMMAND}</span>
232108
</div>
109+
110+
<div className="min-h-[1.4em]" />
111+
<div className="min-h-[1.4em]" />
112+
113+
<div className="text-neutral-500">
114+
{"+ "}
115+
<a
116+
href={CONTRIBUTE_URL}
117+
target="_blank"
118+
rel="noreferrer"
119+
className="text-green-400 transition-colors hover:text-green-300 hover:underline"
120+
>
121+
Add your project
122+
</a>
123+
<span className="text-neutral-600">
124+
{" — open a PR to leaderboard-entries.ts"}
125+
</span>
126+
</div>
233127
</div>
234128
);
235129
};

0 commit comments

Comments
 (0)