Skip to content

Commit 13ef568

Browse files
Merge pull request #155 from hack-rpi/subway-surfers-an-shi
Subway surfers an shi
2 parents 86d65ed + 98baa8f commit 13ef568

File tree

17 files changed

+1456
-1
lines changed

17 files changed

+1456
-1
lines changed

app/api/scores/route.ts

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
// app/api/scores/route.ts
2+
import { NextResponse } from 'next/server';
3+
import mongoose from 'mongoose';
4+
import { Score } from '@/app/models/Score'; // Adjust the import path if necessary
5+
6+
const DB_URI = process.env.MONGO_URI;
7+
8+
const connectToDatabase = async () => {
9+
try {
10+
if (mongoose.connection.readyState >= 1) {
11+
return; // already connected
12+
}
13+
await mongoose.connect(DB_URI!, { useNewUrlParser: true, useUnifiedTopology: true });
14+
console.log('Connected to MongoDB');
15+
} catch (err) {
16+
console.error('MongoDB connection error:', err);
17+
}
18+
};
19+
20+
// Handle POST request to save a score
21+
export async function POST(req: Request) {
22+
await connectToDatabase(); // Ensure DB is connected
23+
24+
try {
25+
const { name, score } = await req.json(); // Get data from the request body
26+
27+
// Create a new score document
28+
const newScore = new Score({ name, score });
29+
await newScore.save();
30+
31+
return NextResponse.json({
32+
message: 'Score saved successfully!',
33+
score: newScore,
34+
});
35+
} catch (err) {
36+
console.error('Error saving score:', err);
37+
return NextResponse.json(
38+
{ error: 'Failed to save the score' },
39+
{ status: 500 }
40+
);
41+
}
42+
}
43+
44+
// Handle GET request to fetch all scores
45+
export async function GET(req: Request) {
46+
await connectToDatabase();
47+
48+
try {
49+
const scores = await Score.find();
50+
return NextResponse.json(scores);
51+
} catch (err) {
52+
console.error('Error retrieving scores:', err);
53+
return NextResponse.json(
54+
{ error: 'Failed to retrieve scores' },
55+
{ status: 500 }
56+
);
57+
}
58+
}

app/globals.css

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,33 @@
7575
}
7676
}
7777

78+
.fancySchmancyButton{
79+
border-radius: 10px;
80+
background-color: white;
81+
width: 140px;
82+
height: 70px;
83+
84+
text-align: center;
85+
outline: none;
86+
letter-spacing: 2px;
87+
word-spacing: 6px;
88+
line-height: 1.5;
89+
text-transform: uppercase;
90+
align-self: center;
91+
margin-bottom: 10px;
92+
transition-duration: 0.2s;
93+
}
94+
95+
.fancySchmancyButton:hover{
96+
transform: scale(1.2);
97+
outline: 3px;
98+
border: 3px white;
99+
background-color: transparent;
100+
color:white;
101+
transition-duration: 0.2s;
102+
103+
}
104+
78105
.bg {
79106
background: url("/backgroundImage.jpg") no-repeat;
80107
background-size: cover;

app/models/Score.ts

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
// models/Score.ts
2+
import mongoose, { Document, Schema, Model } from 'mongoose';
3+
4+
// Define the TypeScript interface for the Score model
5+
interface IScore extends Document {
6+
name: string;
7+
score: number;
8+
}
9+
10+
// Create the Mongoose schema for the Score model
11+
const scoreSchema: Schema = new Schema({
12+
name: { type: String, required: true },
13+
score: { type: Number, required: true },
14+
});
15+
16+
// Create the Mongoose model for the Score
17+
const Score: Model<IScore> = mongoose.models.Score || mongoose.model<IScore>('Score', scoreSchema);
18+
19+
export { Score };

app/surfers/leaderboard/page.tsx

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
"use client";
2+
3+
import { useState, useEffect } from "react";
4+
import NavBar from "@/components/nav-bar/nav-bar";
5+
import "@/app/globals.css";
6+
import HackRPIButton from "@/components/themed-components/hackrpi-button";
7+
8+
const isDirector = false; // Set to `true` to test the director functionality
9+
10+
interface Result {
11+
id: string;
12+
name: string;
13+
score: number;
14+
}
15+
16+
export default function Page() {
17+
const [leaderboardEntries, setLeaderboardEntries] = useState<Result[]>([]);
18+
19+
// Function to fetch leaderboard entries
20+
const fetchLeaderboard = async () => {
21+
try {
22+
const response = await fetch("http://localhost:3000/api/scores");
23+
if (response.ok) {
24+
const data: Result[] = await response.json(); // Ensure the data is typed as Result[]
25+
setLeaderboardEntries(data); // Update state with the fetched leaderboard data
26+
} else {
27+
console.error("Failed to fetch leaderboard data");
28+
}
29+
} catch (error) {
30+
console.error("Error fetching leaderboard:", error);
31+
}
32+
};
33+
34+
useEffect(() => {
35+
fetchLeaderboard(); // Fetch leaderboard when the component mounts
36+
}, []); // Empty dependency array ensures this runs once when the component mounts
37+
38+
return (
39+
<div className="flex flex-col items-center justify-start w-full h-full">
40+
<div className="flex-grow flex-shrink basis-auto">
41+
<h1 className="mt-28 text-center text-4xl font-modern text-hackrpi-orange">2048 Leaderboard</h1>
42+
<table className="min-w-[80vw] mt-10 justify-inbetween table-auto w-full table table-zebra">
43+
<thead>
44+
<tr className="text-white bg-hackrpi-yellow">
45+
<th className="w-1/4 px-4 py-2 text-center font-retro text-white">Position</th>
46+
<th className="w-1/3 px-4 py-2 text-center font-retro text-white">Username</th>
47+
<th className="w-1/3 px-4 py-2 text-center font-retro text-white">Score</th>
48+
{isDirector ? (
49+
<th className="w-1/3 px-4 py-2 font-retro text-white bg-hackrpi-yellow">Delete</th>
50+
) : null}
51+
</tr>
52+
</thead>
53+
54+
<tbody className="text-center text-white font-retro bg-gradient-to-r from-hackrpi-dark-purple to-hackrpi-yellow">
55+
{leaderboardEntries.map((entry, index) => (
56+
<tr key={entry.id}>
57+
<td className="px-y py-2">{index + 1}</td>
58+
<td className="px-4 py-2">{entry.name}</td>
59+
<td className="px-4 py-2">{entry.score}</td>
60+
{isDirector ? (
61+
<td className="px-4 py-2 flex items-center justify-center">
62+
<HackRPIButton
63+
onClick={async () => {
64+
alert("not implemented yet");
65+
}}
66+
>
67+
Delete Item
68+
</HackRPIButton>
69+
</td>
70+
) : null}
71+
</tr>
72+
))}
73+
</tbody>
74+
</table>
75+
</div>
76+
<div className="flex-grow mt-24"></div>
77+
<div className="absolute-bottom-0 w-full"></div>
78+
</div>
79+
);
80+
}

0 commit comments

Comments
 (0)