Update requirements and minor features

This commit is contained in:
2026-05-23 16:50:01 -04:00
parent 471bd05ae6
commit c95cadffa0
4 changed files with 125 additions and 63 deletions
+91 -31
View File
@@ -5,14 +5,15 @@ import "../App.css";
function Leaderboard() {
const [submissions, setSubmissions] = useState([]);
const [message, setMessage] = useState("");
const [sort, setSort] = useState("top");
useEffect(() => {
loadLeaderboard();
}, []);
loadLeaderboard(sort);
}, [sort]);
const loadLeaderboard = async () => {
const loadLeaderboard = async (sortMode) => {
try {
const response = await fetch("/api/leaderboard");
const response = await fetch(`/api/leaderboard?sort=${sortMode}`);
const data = await response.json();
setSubmissions(data);
} catch (error) {
@@ -20,7 +21,6 @@ function Leaderboard() {
}
};
const upvote = async (id) => {
try {
const response = await fetch("/api/upvote", {
@@ -33,7 +33,7 @@ function Leaderboard() {
if (response.ok) {
setMessage("✓ Vote recorded!");
loadLeaderboard();
loadLeaderboard(sort);
setTimeout(() => setMessage(""), 3000);
} else {
setMessage("✗ " + (data.error || "Failed to vote"));
@@ -52,6 +52,10 @@ function Leaderboard() {
});
};
const toggleSort = () => {
setSort((prev) => (prev === "top" ? "new" : "top"));
};
return (
<div
style={{
@@ -73,22 +77,78 @@ function Leaderboard() {
>
<div>
<h1 style={{ margin: 0 }}>Leaderboard</h1>
<button
onClick={loadLeaderboard}
style={{
marginTop: "10px",
padding: "6px 14px",
fontSize: "14px",
cursor: "pointer",
backgroundColor: "transparent",
color: "#f0f0f0",
border: "2px solid #555",
borderRadius: "4px",
display: "block",
}}
>
Refresh
</button>
<div style={{ display: "flex", gap: "10px", marginTop: "10px" }}>
<button
onClick={() => loadLeaderboard(sort)}
style={{
padding: "6px 14px",
fontSize: "14px",
cursor: "pointer",
backgroundColor: "transparent",
color: "#f0f0f0",
border: "2px solid #555",
borderRadius: "4px",
}}
>
Refresh
</button>
{/* Sliding toggle */}
<div
onClick={toggleSort}
style={{
position: "relative",
display: "flex",
alignItems: "center",
width: "120px",
height: "34px",
backgroundColor: "transparent",
border: "2px solid #555",
borderRadius: "4px",
cursor: "pointer",
userSelect: "none",
overflow: "hidden",
fontFamily: "system-ui",
}}
>
{/* Sliding highlight */}
<div
style={{
position: "absolute",
top: 0,
left: sort === "top" ? 0 : "50%",
width: "50%",
height: "100%",
backgroundColor: "#f0f0f0",
transition: "left 0.2s ease",
}}
/>
<span
style={{
position: "relative",
flex: 1,
textAlign: "center",
fontSize: "14px",
color: sort === "top" ? "#111" : "#f0f0f0",
transition: "color 0.2s ease",
}}
>
Top
</span>
<span
style={{
position: "relative",
flex: 1,
textAlign: "center",
fontSize: "14px",
color: sort === "new" ? "#111" : "#f0f0f0",
transition: "color 0.2s ease",
}}
>
New
</span>
</div>
</div>
</div>
<MonkeySprite animation="idle" />
@@ -111,7 +171,7 @@ function Leaderboard() {
<div>
{submissions.length === 0 ? (
<p style={{ textAlign: "center", padding: "40px", color: "#666" }}>
<p style={{ textAlign: "center", padding: "40px", color: "#f0f0f0" }}>
No submissions yet. Be the first!
</p>
) : (
@@ -123,7 +183,7 @@ function Leaderboard() {
marginBottom: "15px",
borderRadius: "8px",
backgroundColor: "#1a1a1a",
border: `1px solid ${index < 3 ? "#555" : "#333"}`,
border: `1px solid ${index < 3 && sort === "top" ? "#555" : "#333"}`,
display: "flex",
alignItems: "center",
gap: "20px",
@@ -134,12 +194,12 @@ function Leaderboard() {
fontSize: "24px",
minWidth: "40px",
color:
index === 0
? "#fff"
: index === 1
? "#aaa"
: index === 2
? "#888"
sort === "top" && index === 0
? "#FFD700"
: sort === "top" && index === 1
? "#C0C0C0"
: sort === "top" && index === 2
? "#CD7F32"
: "#555",
}}
>
@@ -157,7 +217,7 @@ function Leaderboard() {
>
"{sub.phrase}"
</div>
<div style={{ fontSize: "12px", color: "#666" }}>
<div style={{ fontSize: "12px", color: "#f0f0f0" }}>
{formatDate(sub.created_at)}
</div>
</div>
+1 -1
View File
@@ -166,7 +166,7 @@ function Type() {
const response = await fetch("/api/submit", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ phrase, timestamps }),
body: JSON.stringify({ timestamps }),
});
const data = await response.json();