diff --git a/crackcode/client/package-lock.json b/crackcode/client/package-lock.json
index 1386af12..69b6f52f 100644
--- a/crackcode/client/package-lock.json
+++ b/crackcode/client/package-lock.json
@@ -74,6 +74,7 @@
"integrity": "sha512-e7jT4DxYvIDLk1ZHmU/m/mB19rex9sv0c2ftBtjSBv+kVM/902eh0fINUzD7UwLLNR+jU585GxUJ8/EBfAM5fw==",
"dev": true,
"license": "MIT",
+ "peer": true,
"dependencies": {
"@babel/code-frame": "^7.27.1",
"@babel/generator": "^7.28.5",
@@ -1776,6 +1777,7 @@
"integrity": "sha512-z9VXpC7MWrhfWipitjNdgCauoMLRdIILQsAEV+ZesIzBq/oUlxk0m3ApZuMFCXdnS4U7KrI+l3WRUEGQ8K1QKw==",
"dev": true,
"license": "MIT",
+ "peer": true,
"dependencies": {
"@types/prop-types": "*",
"csstype": "^3.2.2"
@@ -1796,8 +1798,7 @@
"resolved": "https://registry.npmjs.org/@types/trusted-types/-/trusted-types-2.0.7.tgz",
"integrity": "sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==",
"license": "MIT",
- "optional": true,
- "peer": true
+ "optional": true
},
"node_modules/@vitejs/plugin-react": {
"version": "5.1.2",
@@ -2007,6 +2008,7 @@
"integrity": "sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw==",
"dev": true,
"license": "MIT",
+ "peer": true,
"bin": {
"acorn": "bin/acorn"
},
@@ -2218,6 +2220,7 @@
}
],
"license": "MIT",
+ "peer": true,
"dependencies": {
"baseline-browser-mapping": "^2.9.0",
"caniuse-lite": "^1.0.30001759",
@@ -2671,7 +2674,6 @@
"resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.2.7.tgz",
"integrity": "sha512-WhL/YuveyGXJaerVlMYGWhvQswa7myDG17P7Vu65EWC05o8vfeNbvNf4d/BOvH99+ZW+LlQsc1GDKMa1vNK6dw==",
"license": "(MPL-2.0 OR Apache-2.0)",
- "peer": true,
"optionalDependencies": {
"@types/trusted-types": "^2.0.7"
}
@@ -2859,6 +2861,7 @@
"integrity": "sha512-LEyamqS7W5HB3ujJyvi0HQK/dtVINZvd5mAAp9eT5S/ujByGjiZLCzPcHVzuXbpJDJF/cxwHlfceVUDZ2lnSTw==",
"dev": true,
"license": "MIT",
+ "peer": true,
"dependencies": {
"@eslint-community/eslint-utils": "^4.8.0",
"@eslint-community/regexpp": "^4.12.1",
@@ -3937,6 +3940,7 @@
"integrity": "sha512-/9AVW7xNbsBv6GfWho4TTNjEo9fe6Zhf9O7s0Fhhr3u+awPwAJMKwAMXnkk5vBxflqLW9hTHX/0cs+P3gW+cQw==",
"dev": true,
"license": "MIT",
+ "peer": true,
"dependencies": {
"abab": "^2.0.6",
"cssstyle": "^3.0.0",
@@ -4399,7 +4403,6 @@
"resolved": "https://registry.npmjs.org/marked/-/marked-14.0.0.tgz",
"integrity": "sha512-uIj4+faQ+MgHgwUW1l2PsPglZLOLOT1uErt06dAPtx2kjteLAkbsd/0FiYg/MGS+i7ZKLb7w2WClxHkzOOuryQ==",
"license": "MIT",
- "peer": true,
"bin": {
"marked": "bin/marked.js"
},
@@ -4802,6 +4805,7 @@
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz",
"integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==",
"license": "MIT",
+ "peer": true,
"engines": {
"node": ">=12"
},
@@ -4945,6 +4949,7 @@
"resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz",
"integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==",
"license": "MIT",
+ "peer": true,
"dependencies": {
"loose-envify": "^1.1.0"
},
@@ -4957,6 +4962,7 @@
"resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz",
"integrity": "sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==",
"license": "MIT",
+ "peer": true,
"dependencies": {
"loose-envify": "^1.1.0",
"scheduler": "^0.23.2"
@@ -5671,6 +5677,7 @@
"resolved": "https://registry.npmjs.org/vite/-/vite-7.3.0.tgz",
"integrity": "sha512-dZwN5L1VlUBewiP6H9s2+B3e3Jg96D0vzN+Ry73sOefebhYr9f94wwkMNN/9ouoU8pV1BqA1d1zGk8928cx0rg==",
"license": "MIT",
+ "peer": true,
"dependencies": {
"esbuild": "^0.27.0",
"fdir": "^6.5.0",
@@ -7039,6 +7046,7 @@
"integrity": "sha512-0wZ1IRqGGhMP76gLqz8EyfBXKk0J2qo2+H3fi4mcUP/KtTocoX08nmIAHl1Z2kJIZbZee8KOpBCSNPRgauucjw==",
"dev": true,
"license": "MIT",
+ "peer": true,
"funding": {
"url": "https://github.com/sponsors/colinhacks"
}
diff --git a/crackcode/client/src/components/leaderboard/leaderboardTable.jsx b/crackcode/client/src/components/leaderboard/leaderboardTable.jsx
index b5e2228f..ffd0d213 100644
--- a/crackcode/client/src/components/leaderboard/leaderboardTable.jsx
+++ b/crackcode/client/src/components/leaderboard/leaderboardTable.jsx
@@ -1,68 +1,164 @@
import React from "react";
import { UserRoundSearch, Flame } from "lucide-react";
-// ── Renders either an or emoji depending on the avatar value ──
const Avatar = ({ avatar, name }) => {
const isImagePath =
typeof avatar === "string" &&
(avatar.startsWith("/") ||
avatar.startsWith("http") ||
avatar.match(/\.(png|jpg|jpeg|gif|webp|svg)$/i));
+
if (isImagePath) {
return (
{ e.target.replaceWith(Object.assign(document.createElement("span"), { textContent: "🕵️" })); }}
+ style={{
+ width: 32, height: 32, borderRadius: "50%", objectFit: "cover",
+ border: "2px solid var(--border)", flexShrink: 0,
+ }}
+ onError={(e) => { e.target.style.display = "none"; }}
/>
);
}
+
const isEmoji = typeof avatar === "string" && /\p{Emoji}/u.test(avatar);
- return {isEmoji ? avatar :
| Rank | -Detective | -Title | -Specialization | -Investigation Points | -Cases Solved | -Streak | +
|---|---|---|---|---|---|---|
| + {label} + | + ))}||||||
| #{user.rank} | -
-
-
- |
- {user.title} | -{user.specialization} | -{user.points.toLocaleString()} | -{user.cases} | -
-
- {user.streak}
- |
-
| + + #{user.rank} + {RANK_MEDAL[user.rank] && ( + {RANK_MEDAL[user.rank]} + )} + + | + + {/* Detective */} +
+
+
+ |
+
+ {/* Title badge */}
+ + + {user.title} + + | + + {/* Specialization */} ++ {user.specialization} + | + + {/* Investigation Points */} ++ {user.points.toLocaleString()} + | + + {/* Cases Solved */} ++ {user.cases} + | + + {/* Streak */} +
+
+
+ |
+