Update requirements and minor features
This commit is contained in:
@@ -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>
|
||||
|
||||
@@ -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();
|
||||
|
||||
Reference in New Issue
Block a user