Skip to content
Open
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
65 changes: 42 additions & 23 deletions client/src/components/common/Navbar.jsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import { useState } from "react";
import { useState, useEffect } from "react";
import { useNavigate } from "react-router-dom";
import { Menu, X } from "lucide-react"; // hamburger + close icons
import avatar from "/avatars/1.png";

export default function Navbar() {
const navigate = useNavigate();
const [menuOpen, setMenuOpen] = useState(false);
const [isLoggedIn, setIsLoggedIn] = useState(false);

const navItems = [
{ label: "Home", path: "/landing" },
Expand All @@ -14,6 +15,23 @@ export default function Navbar() {
{ label: "How to Play", path: "/how-to-play" },
];

useEffect(() => {
const token = localStorage.getItem("token");
setIsLoggedIn(!!token);
Comment on lines +19 to +20
Copy link

Copilot AI Oct 3, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The useEffect should listen for changes to localStorage to handle cases where the token might be modified outside this component. Consider adding a storage event listener or using a context/state management solution for authentication state.

Suggested change
const token = localStorage.getItem("token");
setIsLoggedIn(!!token);
const checkToken = () => {
const token = localStorage.getItem("token");
setIsLoggedIn(!!token);
};
checkToken();
const handleStorage = (event) => {
if (event.key === "token") {
checkToken();
}
};
window.addEventListener("storage", handleStorage);
return () => {
window.removeEventListener("storage", handleStorage);
};

Copilot uses AI. Check for mistakes.
}, []);

const handleAuthAction = () => {
if (isLoggedIn) {
localStorage.removeItem("token");
localStorage.removeItem("user");
setIsLoggedIn(false);
navigate("/login");
} else {
navigate("/login");
}
setMenuOpen(false); // close mobile menu if open
};

return (
<nav className="w-full bg-black text-white font-montserrat shadow-md relative z-50">
<div className="flex items-center justify-between px-6 py-4">
Expand Down Expand Up @@ -41,18 +59,20 @@ export default function Navbar() {
))}

<button
onClick={() => navigate("/login")}
onClick={handleAuthAction}
className="bg-[#FFFB00] text-black w-32 px-4 py-2 rounded-[6px] shadow-[0_0_10px_#FFFB00] hover:scale-105 transition font-silkscreen relative z-10"
>
Login
{isLoggedIn ? "Logout" : "Login"}
</button>

<img
src={avatar}
onClick={() => navigate("/profile")}
alt="profile"
className="w-10 h-10 rounded-full border-[2px] border-[#FFFB00] shadow-[0_0_10px_#FFFB00] cursor-pointer relative z-10"
/>
{isLoggedIn && (
<img
src={avatar}
onClick={() => navigate("/profile")}
alt="profile"
className="w-10 h-10 rounded-full border-[2px] border-[#FFFB00] shadow-[0_0_10px_#FFFB00] cursor-pointer relative z-10"
/>
)}
</div>

{/* Mobile Hamburger */}
Expand Down Expand Up @@ -88,24 +108,23 @@ export default function Navbar() {
))}

<button
onClick={() => {
navigate("/login");
setMenuOpen(false);
}}
onClick={handleAuthAction}
className="bg-[#FFFB00] text-black w-32 px-4 py-2 rounded-[6px] shadow-[0_0_10px_#FFFB00] hover:scale-105 transition font-silkscreen relative z-10"
>
Login
{isLoggedIn ? "Logout" : "Login"}
</button>

<img
src={avatar}
onClick={() => {
navigate("/profile");
setMenuOpen(false);
}}
alt="profile"
className="w-12 h-12 rounded-full border-[2px] border-[#FFFB00] shadow-[0_0_10px_#FFFB00] cursor-pointer relative z-10"
/>
{isLoggedIn && (
<img
src={avatar}
onClick={() => {
navigate("/profile");
setMenuOpen(false);
}}
alt="profile"
className="w-12 h-12 rounded-full border-[2px] border-[#FFFB00] shadow-[0_0_10px_#FFFB00] cursor-pointer relative z-10"
/>
)}
</div>
</nav>
);
Expand Down
7 changes: 7 additions & 0 deletions client/src/pages/HomePage.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,13 @@ import {

const HomePage = () => {
const navigate = useNavigate();
// ✅ Redirect if already logged in
useEffect(() => {
const token = localStorage.getItem("token");
if (token) {
navigate("/landing", { replace: true });
}
}, [navigate]);
Comment on lines +14 to +19
Copy link

Copilot AI Oct 3, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The useEffect hook lacks proper indentation. It should be aligned with other top-level code in the component.

Suggested change
useEffect(() => {
const token = localStorage.getItem("token");
if (token) {
navigate("/landing", { replace: true });
}
}, [navigate]);
useEffect(() => {
const token = localStorage.getItem("token");
if (token) {
navigate("/landing", { replace: true });
}
}, [navigate]);

Copilot uses AI. Check for mistakes.
const blobRef = useRef(null);
const [mousePosition, setMousePosition] = useState({
x: window.innerWidth / 2,
Expand Down
28 changes: 14 additions & 14 deletions client/src/pages/LandingPage.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -34,59 +34,59 @@ export default function LandingPage() {
};

return (
<div className="bg-black text-white font-montserrat h-screen w-screen overflow-hidden flex flex-col">
<div className="bg-black text-white font-montserrat min-h-screen w-full flex flex-col">
<Navbar />

{/* Scale landing body */}
<div className="flex-1 flex items-start sm:items-center justify-center px-4 pt-3 sm:pt-0">
<div className="flex flex-col justify-center items-center w-full scale-[1.05] sm:scale-100 md:scale-[1.25]">
<div className="flex-1 flex items-center justify-center px-4 py-8">
<div className="flex flex-col justify-center items-center w-full max-w-4xl">
{/* Greeting */}
<h1 className="text-3xl sm:text-4xl md:text-5xl font-black mb-6 text-center">
Hello{greeted ? `, ${name}!` : "!"}
</h1>

{/* Mobile Input & Button separated */}
<div className="flex flex-col items-center gap-3 sm:hidden mb-6">
<div className="flex items-center bg-[#FFFB00] px-2 py-1 rounded-[8px] shadow-[0_0_20px_#FFFB00] w-[220px]">
<div className="flex flex-col items-center gap-3 sm:hidden mb-6 w-full max-w-xs">
<div className="flex items-center bg-[#FFFB00] px-2 py-1 rounded-lg shadow-[0_0_20px_#FFFB00] w-full">
<input
type="text"
placeholder="Enter Your Name..."
value={name}
onChange={(e) => setName(e.target.value)}
disabled={isSignedUp}
className="px-2 py-2 w-full text-sm border-2 border-black rounded-[6px] text-black placeholder-black font-silkscreen bg-white outline-black disabled:opacity-50 disabled:cursor-not-allowed"
className="px-2 py-2 w-full text-sm border-2 border-black rounded-md text-black placeholder-black font-silkscreen bg-white outline-black disabled:opacity-50 disabled:cursor-not-allowed"
/>
</div>
<button
onClick={handleEnter}
disabled={isSignedUp}
className="bg-[#FFFB00] w-[140px] h-9 text-black font-silkscreen border border-black text-sm px-4 py-2 rounded-[6px] hover:scale-105 transition cursor-pointer disabled:opacity-50 disabled:cursor-not-allowed"
className="bg-[#FFFB00] w-36 h-9 text-black font-silkscreen border border-black text-sm px-4 py-2 rounded-md hover:scale-105 transition cursor-pointer disabled:opacity-50 disabled:cursor-not-allowed"
>
ENTER
</button>
</div>

{/* Desktop Input + Button inside border */}
<div className="hidden sm:flex flex-row items-center gap-2 bg-[#FFFB00] px-2 py-1 rounded-[8px] shadow-[0_0_25px_#FFFB00] mb-6 w-full max-w-[500px]">
<div className="hidden sm:flex flex-row items-center gap-2 bg-[#FFFB00] px-2 py-1 rounded-lg shadow-[0_0_25px_#FFFB00] mb-6 w-full max-w-lg">
<input
type="text"
placeholder="Enter Your Name..."
value={name}
onChange={(e) => setName(e.target.value)}
disabled={isSignedUp}
className="px-4 py-3 w-full text-base border-2 border-black rounded-[6px] text-black placeholder-black font-silkscreen bg-white outline-black disabled:opacity-50 disabled:cursor-not-allowed"
className="px-4 py-3 w-full text-base border-2 border-black rounded-md text-black placeholder-black font-silkscreen bg-white outline-black disabled:opacity-50 disabled:cursor-not-allowed"
/>
<button
onClick={handleEnter}
disabled={isSignedUp}
className="bg-[#FFFB00] w-auto h-11 text-black font-silkscreen border border-black text-sm px-6 py-[9px] rounded-[6px] hover:scale-105 transition cursor-pointer disabled:opacity-50 disabled:cursor-not-allowed"
className="bg-[#FFFB00] whitespace-nowrap h-11 text-black font-silkscreen border border-black text-sm px-6 py-2 rounded-md hover:scale-105 transition cursor-pointer disabled:opacity-50 disabled:cursor-not-allowed"
>
ENTER
</button>
</div>

{/* Avatar Selector */}
<div className="scale-[1.05] sm:scale-100">
<div className="w-full flex justify-center mb-8">
<AvatarSelector
selectedAvatar={avatar}
onSelect={(a) => {
Expand All @@ -98,15 +98,15 @@ export default function LandingPage() {
</div>

{/* Join/Create Buttons */}
<div className="flex flex-col md:flex-row gap-6 md:gap-12 mt-8 w-full items-center justify-center">
<div className="flex flex-col md:flex-row gap-6 md:gap-12 w-full items-center justify-center">
<div className="flex flex-col items-center w-full sm:w-auto">
<p className="text-sm sm:text-base font-bold mb-2">
Have A Room-Code?
</p>
<GlowingButton
text="JOIN A ROOM"
color="white"
className="w-[200px] sm:w-[220px] md:w-[240px] lg:w-[280px] font-silkscreen text-sm sm:text-base md:text-lg"
className="w-52 sm:w-56 md:w-60 lg:w-72 font-silkscreen text-sm sm:text-base md:text-lg"
onClick={() => navigate("/join-room")}
disabled={!name.trim() || !avatar}
/>
Expand All @@ -118,7 +118,7 @@ export default function LandingPage() {
<GlowingButton
text="CREATE A ROOM"
color="yellow"
className="w-[200px] sm:w-[220px] md:w-[240px] lg:w-[280px] font-silkscreen text-sm sm:text-base md:text-lg"
className="w-52 sm:w-56 md:w-60 lg:w-72 font-silkscreen text-sm sm:text-base md:text-lg"
onClick={() => navigate("/create-room")}
disabled={!name.trim() || !avatar}
/>
Expand Down