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
253 changes: 137 additions & 116 deletions frontend/src/Components/Navbar/Navbar.jsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
// src/Components/Navbar/Navbar.jsx
import React, { useEffect, useState } from "react";
import {
UserCircle,
Expand All @@ -8,11 +7,13 @@ import {
Github,
Phone,
HelpCircle,
X,
} from "lucide-react";
import { FloatingNav } from "../ui/floating-navbar";
import { Link, useNavigate } from "react-router-dom";
import DarkModeToggle from "../ui/DarkModeToggle";
import { useTimer } from "../../context/TimerContext";
// import "./MobileNav.css"; // Import the new CSS file - REMOVED

const publicNavItems = [
{
Expand Down Expand Up @@ -42,6 +43,74 @@ const publicNavItems = [
},
];

// --- Mobile Navigation Overlay Component ---
// Kept in the same file for simplicity
const MobileNavOverlay = ({ isOpen, onClose, navItems, isAuthenticated, handleLogout }) => {
const overlayClasses = `mobile-nav-overlay ${isOpen ? "open" : ""}`;

const handleLinkClick = () => {
onClose();
};

const handleLogoutClick = () => {
handleLogout();
onClose();
}

return (
<div className={overlayClasses}>
<button onClick={onClose} className="close-btn">
<X size={32} />
</button>

<nav>
<ul>
{!isAuthenticated ? (
navItems.map((item) => (
<li key={item.name}>
<a href={item.link} onClick={handleLinkClick}>
{item.name}
</a>
</li>
))
) : (
<>
<li>
<Link to="/profile" onClick={handleLinkClick}>
Profile
</Link>
</li>
{/* You can add more authenticated user links here */}
</>
)}
</ul>
</nav>

<div className="mobile-nav-footer">
{!isAuthenticated ? (
<>
<Link to="/register" className="w-full">
<button onClick={handleLinkClick} className="signup-btn-mobile">
Sign Up
</button>
</Link>
<DarkModeToggle />
</>
) : (
<>
<button onClick={handleLogoutClick} className="logout-btn-mobile">
Logout
</button>
<DarkModeToggle />
</>
)}
</div>
</div>
);
};


// --- Main Navbar Component ---
const Navbar = () => {
const [showFloating, setShowFloating] = useState(false);
const [menuOpen, setMenuOpen] = useState(false);
Expand Down Expand Up @@ -90,8 +159,6 @@ const Navbar = () => {
style={{ background: "var(--card)", borderColor: "var(--border)" }}
>
<div className="mx-auto mr-1 flex max-w-7xl items-center justify-between">
{/* Logo */}

<Link to="/">
<h1
className="text-2xl md:text-3xl lg:text-4xl font-extrabold tracking-tight hover:scale-105 transition-transform duration-300"
Expand All @@ -101,71 +168,70 @@ const Navbar = () => {
</h1>
</Link>

{/* Desktop Navigation - visible from lg */}
{/* Desktop Navigation */}
<nav className="hidden lg:flex space-x-6 lg:space-x-8 items-center">
{!isAuthenticated &&
publicNavItems.map((item) => (
<a
key={item.name}
href={item.link}
className="relative text-[15px] md:text-[16px] lg:text-[17px] font-medium transition-all duration-300 group flex items-center gap-2"
style={{ color: "var(--card-foreground)" }}
>
{item.icon} <span>{item.name}</span>
<span className="absolute left-0 -bottom-1 w-0 h-[2px] bg-gradient-to-r from-[var(--primary)] to-purple-500 transition-all duration-500 group-hover:w-full"></span>
</a>
))}

{isAuthenticated && isRunning && (
<div
onClick={() => navigate("/pomodoro")}
className="flex items-center gap-2 cursor-pointer px-3 py-1 rounded-lg transition-all duration-300 hover:bg-gray-200 dark:hover:bg-gray-700 hover:shadow-md hover:shadow-[var(--primary)]/30"
>
<Clock className="w-5 h-5 text-blue-500 animate-pulse" />
<span className="text-sm font-mono">{displayTime}</span>
</div>
)}

{/* Auth Section */}
{isAuthenticated ? (
<div className="flex items-center gap-3 ml-4">
<Link
to="/profile"
className="flex items-center gap-2 text-[16px] lg:text-[17px] font-medium relative group"
style={{ color: "var(--primary)" }}
>
<UserCircle className="h-4 w-4" /> <span>Profile</span>
<span className="absolute left-0 -bottom-1 w-0 h-[2px] bg-gradient-to-r from-[var(--primary)] to-purple-500 transition-all duration-500 group-hover:w-full"></span>
</Link>
<button
onClick={handleLogout}
className="text-[16px] lg:text-[17px] font-medium text-red-500 transition-colors duration-300 hover:text-red-600"
>
Logout
</button>
<DarkModeToggle />
</div>
) : (
<div className="flex items-center gap-3 ml-4">
<Link to="/register">
<button className="px-4 md:px-5 lg:px-6 py-2 rounded-md font-semibold bg-[var(--primary)] text-[var(--primary-foreground)] shadow-md transition-transform duration-300 hover:scale-105 hover:shadow-lg cursor-pointer text-sm md:text-base">
Sign Up
</button>
</Link>
<DarkModeToggle />
</div>
)}
{!isAuthenticated &&
publicNavItems.map((item) => (
<a
key={item.name}
href={item.link}
className="relative text-[15px] md:text-[16px] lg:text-[17px] font-medium transition-all duration-300 group flex items-center gap-2"
style={{ color: "var(--card-foreground)" }}
>
{item.icon} <span>{item.name}</span>
<span className="absolute left-0 -bottom-1 w-0 h-[2px] bg-gradient-to-r from-[var(--primary)] to-purple-500 transition-all duration-500 group-hover:w-full"></span>
</a>
))}

{isAuthenticated && isRunning && (
<div
onClick={() => navigate("/pomodoro")}
className="flex items-center gap-2 cursor-pointer px-3 py-1 rounded-lg transition-all duration-300 hover:bg-gray-200 dark:hover:bg-gray-700 hover:shadow-md hover:shadow-[var(--primary)]/30"
>
<Clock className="w-5 h-5 text-blue-500 animate-pulse" />
<span className="text-sm font-mono">{displayTime}</span>
</div>
)}

{isAuthenticated ? (
<div className="flex items-center gap-3 ml-4">
<Link
to="/profile"
className="flex items-center gap-2 text-[16px] lg:text-[17px] font-medium relative group"
style={{ color: "var(--primary)" }}
>
<UserCircle className="h-4 w-4" /> <span>Profile</span>
<span className="absolute left-0 -bottom-1 w-0 h-[2px] bg-gradient-to-r from-[var(--primary)] to-purple-500 transition-all duration-500 group-hover:w-full"></span>
</Link>
<button
onClick={handleLogout}
className="text-[16px] lg:text-[17px] font-medium text-red-500 transition-colors duration-300 hover:text-red-600"
>
Logout
</button>
<DarkModeToggle />
</div>
) : (
<div className="flex items-center gap-3 ml-4">
<Link to="/register">
<button className="px-4 md:px-5 lg:px-6 py-2 rounded-md font-semibold bg-[var(--primary)] text-[var(--primary-foreground)] shadow-md transition-transform duration-300 hover:scale-105 hover:shadow-lg cursor-pointer text-sm md:text-base">
Sign Up
</button>
</Link>
<DarkModeToggle />
</div>
)}
</nav>

{/* Mobile & Tablet Hamburger */}
<div className="lg:hidden">
<button
onClick={() => setMenuOpen(!menuOpen)}
className="relative w-8 h-6 flex flex-col justify-between items-center"
className="relative w-8 h-6 flex flex-col justify-between items-center z-[110]" // Higher z-index for the button
>
<span
className={`block h-1 w-full bg-current rounded transform transition duration-300 ease-in-out ${
menuOpen ? "rotate-45 translate-y-2" : ""
className={`block h-1 w-full rounded transform transition duration-300 ease-in-out ${
menuOpen ? "rotate-45 translate-y-[9px] bg-white" : "bg-current"
}`}
/>
<span
Expand All @@ -174,71 +240,25 @@ const Navbar = () => {
}`}
/>
<span
className={`block h-1 w-full bg-current rounded transform transition duration-300 ease-in-out ${
menuOpen ? "-rotate-45 -translate-y-2" : ""
className={`block h-1 w-full rounded transform transition duration-300 ease-in-out ${
menuOpen ? "-rotate-45 -translate-y-[9px] bg-white" : "bg-current"
}`}
/>
</button>

{menuOpen && (
<div className="mt-4 flex flex-col gap-3 px-4 pb-4">
{!isAuthenticated ? (
<>
{publicNavItems.map((item) => (
<a
key={item.name}
href={item.link}
className="relative text-[15px] md:text-[16px] font-medium transition-all duration-300 group flex items-center gap-2"
style={{ color: "var(--card-foreground)" }}
>
{item.icon} <span>{item.name}</span>
<span className="absolute left-0 -bottom-1 w-0 h-[2px] bg-gradient-to-r from-[var(--primary)] to-purple-500 transition-all duration-500 group-hover:w-full"></span>
</a>
))}
<Link to="/register">
<button className="cursor-pointer w-full px-4 md:px-5 py-2 mt-2 rounded-md font-semibold bg-[var(--primary)] text-[var(--primary-foreground)] shadow-md transition-transform duration-300 hover:scale-105 hover:shadow-lg text-sm md:text-base">
Sign Up
</button>
</Link>
<DarkModeToggle />
</>
) : (
<>
<Link
to="/profile"
className="relative flex items-center gap-2 text-[16px] font-medium group"
style={{ color: "var(--primary)" }}
>
<UserCircle className="h-4 w-4" /> <span>Profile</span>
<span className="absolute left-0 -bottom-1 w-0 h-[2px] bg-gradient-to-r from-[var(--primary)] to-purple-500 transition-all duration-500 group-hover:w-full"></span>
</Link>
{isRunning && (
<div
onClick={() => navigate("/pomodoro")}
className="flex items-center gap-2 cursor-pointer hover:shadow-md hover:shadow-[var(--primary)]/30 transition-all duration-300"
>
<Clock className="w-5 h-5 text-blue-500 animate-pulse" />
<span className="text-sm font-mono">
{displayTime}
</span>
</div>
)}
<button
onClick={handleLogout}
className="text-[16px] font-medium text-red-500 hover:text-red-600 transition-colors"
>
Logout
</button>
<DarkModeToggle />
</>
)}
</div>
)}
</div>
</div>
</header>
)}

{/* Render the full-screen overlay */}
<MobileNavOverlay
isOpen={menuOpen}
onClose={() => setMenuOpen(false)}
navItems={publicNavItems}
isAuthenticated={isAuthenticated}
handleLogout={handleLogout}
/>

{showFloating && (
<FloatingNav navItems={!isAuthenticated ? publicNavItems : []} />
)}
Expand All @@ -247,3 +267,4 @@ const Navbar = () => {
};

export default Navbar;

73 changes: 73 additions & 0 deletions frontend/src/Components/Navbar/NavbarOverlay.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
// src/Components/Navbar/MobileNavOverlay.jsx

import React from "react";
import { Link } from "react-router-dom";
import { X, UserCircle, Clock } from "lucide-react";
import DarkModeToggle from "../ui/DarkModeToggle";

const MobileNavOverlay = ({
isOpen,
onClose,
navItems,
isAuthenticated,
handleLogout,
}) => {
// Use a template literal to conditionally apply the 'open' class
const overlayClasses = `mobile-nav-overlay ${isOpen ? "open" : ""}`;

return (
<div className={overlayClasses}>
<button onClick={onClose} className="close-btn">
<X size={32} />
</button>

{/* Main Navigation Links */}
<nav>
<ul>
{!isAuthenticated &&
navItems.map((item) => (
<li key={item.name}>
<a href={item.link} onClick={onClose}>
{item.name}
</a>
</li>
))}

{isAuthenticated && (
<>
<li>
<Link to="/profile" onClick={onClose}>
Profile
</Link>
</li>
{/* Add other authenticated links here if needed */}
</>
)}
</ul>
</nav>

{/* Footer Actions */}
<div className="mobile-nav-footer">
{!isAuthenticated ? (
<>
<Link to="/register" className="w-full">
<button onClick={onClose} className="signup-btn-mobile">
Sign Up
</button>
</Link>
<DarkModeToggle />
</>
) : (
<>
<button onClick={handleLogout} className="logout-btn-mobile">
Logout
</button>
<DarkModeToggle />
</>
)}
</div>
</div>
);
};

export default MobileNavOverlay;
Loading