Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions next.config.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import path from "path";

import type { NextConfig } from "next";

const nextConfig: NextConfig = {
Expand All @@ -19,6 +21,9 @@ const nextConfig: NextConfig = {
},
],
},
turbopack: {
root: __dirname,
},
};

export default nextConfig;
17,668 changes: 10,812 additions & 6,856 deletions package-lock.json

Large diffs are not rendered by default.

41 changes: 21 additions & 20 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,46 +16,47 @@
"dependencies": {
"agenda": "^5.0.0",
"apicalypse": "^1.0.5",
"axios": "^1.10.0",
"axios": "^1.11.0",
"bcryptjs": "^3.0.2",
"daisyui": "^5.0.46",
"daisyui": "^5.0.54",
"email-validator": "^2.0.4",
"jsonwebtoken": "^9.0.2",
"mongoose": "^8.18.0",
"next": "15.3.2",
"nodemailer": "^7.0.3",
"react": "^19.0.0",
"react-dom": "^19.0.0",
"react-hot-toast": "^2.5.2"
"nes.css": "^2.2.1",
"next": "15.5.2",
"nodemailer": "^7.0.6",
"react": "^19.1.1",
"react-dom": "^19.1.1",
"react-hot-toast": "^2.6.0"
},
"devDependencies": {
"@babel/core": "^7.27.7",
"@babel/preset-env": "^7.27.2",
"@babel/core": "^7.28.3",
"@babel/preset-env": "^7.28.3",
"@eslint/eslintrc": "^3",
"@shelf/jest-mongodb": "^5.2.2",
"@tailwindcss/postcss": "^4.1.11",
"@types/bcryptjs": "^2.4.6",
"@types/jest": "^29.5.14",
"@tailwindcss/postcss": "^4.1.12",
"@types/bcryptjs": "^3.0.0",
"@types/jest": "^30.0.0",
"@types/jsonwebtoken": "^9.0.10",
"@types/node": "^20.19.9",
"@types/nodemailer": "^6.4.17",
"@types/node": "^24.3.0",
"@types/nodemailer": "^7.0.1",
"@types/react": "^19",
"@types/react-dom": "^19",
"autoprefixer": "^10.4.21",
"axios-mock-adapter": "^2.1.0",
"babel-jest": "^29.7.0",
"babel-jest": "^30.1.2",
"dotenv": "^17.2.1",
"eslint": "^9",
"eslint-config-next": "15.3.2",
"jest": "^29.7.0",
"eslint-config-next": "15.5.2",
"jest": "^30.1.2",
"mongodb-memory-server": "^10.2.0",
"postcss": "^8.5.6",
"prompt-sync": "^4.2.0",
"supertest": "^7.1.4",
"tailwindcss": "^4.1.12",
"ts-jest": "^29.3.4",
"ts-jest": "^29.4.1",
"ts-node": "^10.9.2",
"tsx": "^4.20.3",
"typescript": "^5.8.3"
"tsx": "^4.20.5",
"typescript": "^5.9.2"
}
}
Binary file added public/background/orig_big.webp
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/keyboard_logo/pressed/pressed0.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/keyboard_logo/pressed/pressed1.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/keyboard_logo/pressed/pressed2.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/keyboard_logo/pressed/pressed3.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/keyboard_logo/pressed/pressed4.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/keyboard_logo/pressed/pressed5.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/keyboard_logo/pressed/pressed6.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/keyboard_logo/unpressed/unpressed0.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/keyboard_logo/unpressed/unpressed1.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/keyboard_logo/unpressed/unpressed2.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/keyboard_logo/unpressed/unpressed3.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/keyboard_logo/unpressed/unpressed4.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/keyboard_logo/unpressed/unpressed5.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/keyboard_logo/unpressed/unpressed6.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
23 changes: 23 additions & 0 deletions src/app/(navgroup)/footer.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { useEffect, useState } from "react";

export default function Footer() {
const [year, setYear] = useState(new Date().getFullYear());

useEffect(() => {
setYear(new Date().getFullYear());
}, []);
return (
<footer className="flex flex-col justify-center text-center items-center p-4 text-white">
<p className="text-2xl">© {year ?? ""} Delta. All rights reserved.</p>
<p className="text-2xl">Find me on Github!</p>
<a
className="nes-icon github is-large"
href="https://github.com/deltathecreatorr"
></a>
<a
className="nes-icon linkedin is-large"
href="https://www.linkedin.com/in/julio-anandaraaj-developer"
></a>
</footer>
);
}
80 changes: 78 additions & 2 deletions src/app/(navgroup)/home/page.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,88 @@
"use client";
import React from "react";
import React, { useEffect, useState } from "react";
import { Toaster } from "react-hot-toast";
import axios from "axios";
import { Press_Start_2P } from "next/font/google";

const pressStart2P = Press_Start_2P({
weight: "400",
subsets: ["latin"],
});

export default function Home() {
const [gameCount, setGameCount] = useState<number>(0);
const [userCount, setUserCount] = useState<number>(0);

useEffect(() => {
const fetchGameCount = async () => {
try {
const response = await axios.get("/api/igdb/gameCount");
setGameCount(response.data.gameCount);
} catch (error) {
console.error("Error fetching game count:", error);
}
};

const fetchUserCount = async () => {
try {
const response = await axios.get("/api/users/userCount");
setUserCount(response.data.userCount);
} catch (error) {
console.error("Error fetching user count:", error);
}
};

fetchGameCount();
fetchUserCount();
}, []);

return (
<main className="flex flex-col">
<Toaster position="top-left" reverseOrder={false} />
<div></div>
<div className="grow p-8">
<div className="nes-container is-centered is-dark grow text-2xl ">
<p className="text-purple-500 text-4xl">Loadout?</p>
<p className="font-mono">
Loadout is your place to track your game collection and manage your
gaming library. Share what games you own, have played, and want to
play with others. Register an account to get started!
</p>
<div className="flex flex-wrap gap-[4] justify-center">
<button
type="button"
className="btn bg-purple-700 btn-xs sm:btn-sm md:btn-md lg:btn-lg xl:btn-xl"
onClick={() => (window.location.href = "/login")}
>
Login
</button>
<button
type="button"
className="btn bg-purple-700 btn-xs sm:btn-sm md:btn-md lg:btn-lg xl:btn-xl"
onClick={() => (window.location.href = "/register")}
>
Register
</button>
</div>
</div>
<div>
<div className="flex justify-center p-4">
<div className="grid grid-cols-2 gap-5 w-full text-center max-w-xl">
<div className="flex flex-col p-4 bg-purple-800 rounded-box">
<span className="countdown justify-center text-6xl">
<>{gameCount}</>
</span>
<div className="text-4xl">Games Available</div>
</div>
<div className="flex flex-col p-4 bg-purple-800 rounded-box">
<span className="countdown justify-center text-6xl">
<>{userCount}</>
</span>
<div className="text-4xl">Users Reviewing Games</div>
</div>
</div>
</div>
</div>
</div>
</main>
);
}
20 changes: 8 additions & 12 deletions src/app/(navgroup)/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,9 @@

import { useEffect, useState } from "react";
import { usePathname } from "next/navigation";
import Image from "next/image";
import Navbar from "./navbar";
import Logo from "./logo";
import Navigation from "./navbar";
import Footer from "./footer";
import axios from "axios";

export default function NavbarLayout({
Expand All @@ -29,18 +30,13 @@ export default function NavbarLayout({
}, [pathname]); // Re-run when route changes

return (
<div className="min-h-screen bg-gradient-to-t from-black to-purple-600">
<div className="flex flex-col justify-center items-center">
<Image
src={"/images/logo.gif"}
width={320}
height={200}
priority={true}
alt="logo"
></Image>
<div>
<div className="flex flex-col justify-center items-center pt-4">
<Logo />
</div>
<Navbar isVerified={isUserVerified} />
<Navigation isVerified={isUserVerified} />
{children}
<Footer />
</div>
);
}
73 changes: 73 additions & 0 deletions src/app/(navgroup)/logo.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
"use client";
import Image from "next/image";
import React, { useState } from "react";

interface LogoLetterKeys<T> {
[letterKey: string]: T;
}

const UNPRESSED_LETTERS: LogoLetterKeys<string> = {
L: "/keyboard_logo/unpressed/unpressed0.png",
O1: "/keyboard_logo/unpressed/unpressed1.png",
A: "/keyboard_logo/unpressed/unpressed2.png",
D: "/keyboard_logo/unpressed/unpressed3.png",
O2: "/keyboard_logo/unpressed/unpressed4.png",
U: "/keyboard_logo/unpressed/unpressed5.png",
T: "/keyboard_logo/unpressed/unpressed6.png",
};

const PRESSED_LETTERS: LogoLetterKeys<string> = {
L: "/keyboard_logo/pressed/pressed0.png",
O1: "/keyboard_logo/pressed/pressed1.png",
A: "/keyboard_logo/pressed/pressed2.png",
D: "/keyboard_logo/pressed/pressed3.png",
O2: "/keyboard_logo/pressed/pressed4.png",
U: "/keyboard_logo/pressed/pressed5.png",
T: "/keyboard_logo/pressed/pressed6.png",
};

function LogoLetters({
letterKey,
}: {
letterKey: keyof typeof UNPRESSED_LETTERS;
}) {
const [hover, setHover] = useState(false);

return (
<>
{hover ? (
<Image
src={PRESSED_LETTERS[letterKey]}
alt="Logo"
onMouseEnter={() => setHover(true)}
onMouseLeave={() => setHover(false)}
width={104}
height={96}
/>
) : (
<Image
src={UNPRESSED_LETTERS[letterKey]}
alt="Logo"
onMouseEnter={() => setHover(true)}
onMouseLeave={() => setHover(false)}
width={104}
height={96}
/>
)}
</>
);
}

export default function Logo() {
return (
<div className="flex align-center justify-center ">
<LogoLetters letterKey="L" />
<LogoLetters letterKey="O1" />
<LogoLetters letterKey="A" />
<LogoLetters letterKey="D" />
<LogoLetters letterKey="O2" />
<LogoLetters letterKey="U" />
<LogoLetters letterKey="T" />
</div>
);
}
6 changes: 3 additions & 3 deletions src/app/(navgroup)/navbar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
import Link from "next/link";
import { useState } from "react";

export default function Navbar({ isVerified }: { isVerified: boolean }) {
export default function Navigation({ isVerified }: { isVerified: boolean }) {
const [isMenuOpen, setIsMenuOpen] = useState(false);
const navbarItems: string[] = [];
const toggleMenu = () => {
Expand All @@ -16,7 +16,7 @@ export default function Navbar({ isVerified }: { isVerified: boolean }) {
}

return (
<nav
<div
className="w-full max-w-screen px-4 py-4 mx-auto flex top-0 left-0 z-50 menu-toggle justify-center"
onClick={toggleMenu}
>
Expand All @@ -37,6 +37,6 @@ export default function Navbar({ isVerified }: { isVerified: boolean }) {
);
})}
</ul>
</nav>
</div>
);
}
22 changes: 22 additions & 0 deletions src/app/api/igdb/gameCount/route.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { NextResponse } from "next/server";
import Game from "@/models/gameModel.js";
import mongoose from "mongoose";
import { connectToDatabase } from "@/dbConfig/dbConfig";

export async function GET() {
try {
if (mongoose.connection.readyState !== 1) {
await connectToDatabase();
}

const gameCount = await Game.countDocuments();

return NextResponse.json({ gameCount });
} catch (error: any) {
console.error("Error fetching game count:", error);
return NextResponse.json(
{ error: "Failed to fetch game count" },
{ status: 500 }
);
}
}
22 changes: 22 additions & 0 deletions src/app/api/users/userCount/route.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { NextResponse } from "next/server";
import User from "@/models/userModel";
import mongoose from "mongoose";
import { connectToDatabase } from "@/dbConfig/dbConfig";

export async function GET() {
try {
if (mongoose.connection.readyState !== 1) {
await connectToDatabase();
}

const userCount = await User.countDocuments();

return NextResponse.json({ userCount });
} catch (error: any) {
console.error("Error fetching user count:", error);
return NextResponse.json(
{ error: "Failed to fetch user count" },
{ status: 500 }
);
}
}
Loading