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
282 changes: 100 additions & 182 deletions RestroHub-FrontEnd/src/components/customer/Navigation.jsx
Original file line number Diff line number Diff line change
@@ -1,263 +1,181 @@
import React, { useState, useEffect } from 'react';
import { Link, useNavigate } from 'react-router-dom';
import { useSiteData } from '@context/SiteContext.jsx';

// ============================================
// NAVIGATION COMPONENT
// Responsive navbar with scroll effects
// ============================================

const Navigation = () => {
const { siteData } = useSiteData();
const navigate = useNavigate();
const [scrolled, setScrolled] = useState(false);
const [mobileMenuOpen, setMobileMenuOpen] = useState(false);

// Navbar background change on scroll
useEffect(() => {
const handleScroll = () => {
setScrolled(window.scrollY > 100);
setScrolled(window.scrollY > 50);
};

window.addEventListener('scroll', handleScroll);
return () => window.removeEventListener('scroll', handleScroll);
}, []);

// Close mobile menu on resize
useEffect(() => {
const handleResize = () => {
if (window.innerWidth >= 768) {
setMobileMenuOpen(false);
}
};

window.addEventListener('resize', handleResize);
return () => window.removeEventListener('resize', handleResize);
}, []);

// Prevent body scroll when mobile menu is open
useEffect(() => {
document.body.style.overflow = mobileMenuOpen ? 'hidden' : '';
return () => {
document.body.style.overflow = '';
};
}, [mobileMenuOpen]);

if (!siteData) return null;

const handleNavClick = () => {
const handleLogoClick = (e) => {
e.preventDefault();
navigate('/');
window.scrollTo({ top: 0, behavior: 'smooth' });
setMobileMenuOpen(false);
};

return (
<nav className={`nav ${scrolled ? 'nav-scrolled' : ''}`}>
<div className="nav-container">
{/* Logo */}
<a href="#" className="nav-logo font-heading">
<Link to="/" className="nav-logo" onClick={handleLogoClick}>
{siteData.brand.logo ? (
<img src={siteData.brand.logo} alt={siteData.brand.name} />
) : (
siteData.brand.name
)}
</a>
</Link>

{/* Desktop Menu */}
<div className="nav-links">
{siteData.navigation.map((item, index) => (
<a
key={index}
href={item.href}
className="nav-link"
>
<a key={index} href={item.href} className="nav-link">
{item.label}
</a>
))}
</div>

{/* Reserve Button */}
<a href="#reservations" className="nav-reserve btn btn-outline">
Reserve
</a>

{/* Mobile Menu Button */}
<button
className="nav-mobile-btn"
className="nav-mobile-btn"
onClick={() => setMobileMenuOpen(!mobileMenuOpen)}
aria-label="Toggle menu"
>
{mobileMenuOpen ? (
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2">
<path d="M6 18L18 6M6 6l12 12" />
</svg>
) : (
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2">
<path d="M4 6h16M4 12h16M4 18h16" />
</svg>
)}
{mobileMenuOpen ? "✕" : "☰"}
</button>
</div>

{/* Mobile Menu */}
<div className={`nav-mobile-menu ${mobileMenuOpen ? 'open' : ''}`}>
{siteData.navigation.map((item, index) => (
<a
key={index}
href={item.href}
className="nav-mobile-link"
onClick={handleNavClick}
className="nav-mobile-link"
onClick={() => setMobileMenuOpen(false)}
>
{item.label}
</a>
))}
<a
href="#reservations"
className="btn btn-outline nav-mobile-reserve"
onClick={handleNavClick}
>
Reserve a Table
</a>
</div>

<style>{`
.nav {
position: fixed;
top: 0;
left: 0;
right: 0;
z-index: var(--z-fixed);
padding: 12px 16px;
transition: all var(--transition-normal);
}

@media (min-width: 768px) {
.nav {
padding: var(--spacing-lg) var(--spacing-xl);
}
}

.nav-container {
max-width: 1280px;
margin: 0 auto;
display: flex;
justify-content: space-between;
align-items: center;
gap:12px;
flex-wrap:nowrap;
}

.nav-logo {
font-size: var(--text-lg);
font-weight: 700;
letter-spacing: 0.1em;
color: var(--color-text-primary);
text-decoration: none;
.nav {
position: fixed;
top: 0;
left: 0;
right: 0;
z-index: var(--z-fixed, 1000);
padding: 12px 16px;
transition: all var(--transition-normal, 0.3s);
}
.nav-scrolled {
background: white;
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
}

@media (min-width: 768px) {
.nav-logo {
font-size: var(--text-2xl);
}
}

.nav-logo img {
height: 40px;
width: auto;
.nav { padding: var(--spacing-lg, 20px) var(--spacing-xl, 40px); }
}
.nav-container {
max-width: 1280px;
margin: 0 auto;
display: flex;
justify-content: space-between;
align-items: center;
gap: 12px;
flex-wrap: nowrap;
}
.nav-logo {
display: flex;
align-items: center;
font-size: var(--text-lg, 18px);
font-weight: 700;
letter-spacing: 0.1em;
color: var(--color-text-primary, #333);
text-decoration: none;
}

.nav-links {
display: none;
align-items: center;
gap: var(--spacing-xl);
}

@media (min-width: 768px) {
.nav-links {
display: flex;
}
.nav-logo { font-size: var(--text-2xl, 24px); }
}

.nav-link {
color: var(--color-text-primary);
text-decoration: none;
font-size: var(--text-sm);
letter-spacing: 0.15em;
text-transform: uppercase;
transition: color var(--transition-normal);
.nav-logo img {
height: 40px;
width: auto;
}

.nav-link:hover {
color: var(--color-primary);
.nav-links {
display: none;
align-items: center;
gap: var(--spacing-xl, 20px);
}

.nav-reserve {
display: none;
padding: var(--spacing-sm) var(--spacing-lg);
}

@media (min-width: 768px) {
.nav-reserve {
display: block;
}
.nav-links { display: flex; }
}
.nav-link {
color: var(--color-text-primary, #333);
text-decoration: none;
font-size: var(--text-sm, 13px);
font-weight: 600;
letter-spacing: 0.15em;
text-transform: uppercase;
transition: color var(--transition-normal, 0.3s);
}
.nav-link:hover {
color: var(--color-primary, #007bff);
}
.nav-mobile-btn {
display: block;
background: none;
border: none;
color: var(--color-text-primary, #333);
font-size: 24px;
cursor: pointer;
padding: var(--spacing-sm, 8px);
}

.nav-mobile-btn {
display: block;
background: none;
border: none;
color: var(--color-text-primary);
cursor: pointer;
padding: var(--spacing-sm);
}

@media (min-width: 768px) {
.nav-mobile-btn {
display: none;
}
.nav-mobile-btn { display: none; }
}

.nav-mobile-btn svg {
width: 24px;
height: 24px;
}

.nav-mobile-menu {
position: fixed;
top: 64px;
left: 0;
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: var(--color-bg-primary);
display: flex;
height: 100vh;
background: var(--color-bg-primary, white);
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
gap: var(--spacing-xl);
align-items: center;
justify-content: center;
gap: var(--spacing-xl, 30px);
transform: translateY(-100%);
transition: all var(--transition-normal, 0.4s);
opacity: 0;
visibility: hidden;
transition: all var(--transition-normal);
}

.nav-mobile-menu.open {
.nav-mobile-menu.open {
transform: translateY(0);
opacity: 1;
visibility: visible;
}

.nav-mobile-link {
color: var(--color-text-primary);
text-decoration: none;
font-size: var(--text-lg);
letter-spacing: 0.15em;
text-transform: uppercase;
transition: color var(--transition-normal);
.nav-mobile-link {
color: var(--color-text-primary, #333);
text-decoration: none;
font-size: var(--text-lg, 18px);
letter-spacing: 0.15em;
text-transform: uppercase;
transition: color var(--transition-normal, 0.3s);
}

.nav-mobile-link:hover {
color: var(--color-primary);
}

.nav-mobile-reserve {
margin-top: var(--spacing-lg);
.nav-mobile-link:hover {
color: var(--color-primary, #007bff);
}
`}</style>
</nav>
);
};

export default Navigation;
export default Navigation;
10 changes: 7 additions & 3 deletions RestroHub-FrontEnd/src/pages/public/Landing.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -287,14 +287,18 @@ const [contactForm, setContactForm] = useState({
<div className="flex h-16 items-center justify-between sm:h-20">

{/* Logo */}
<a href="#" className="flex items-center gap-2.5">
<Link
to="/"
className="flex items-center gap-2.5"
onClick={() => window.scrollTo({ top: 0, behavior: 'smooth' })}
>
<div className="flex h-9 w-9 items-center justify-center rounded-xl bg-blue-600 shadow-md shadow-blue-200 sm:h-10 sm:w-10">
<UtensilsCrossed className="h-5 w-5 text-white" />
</div>
<span className="text-xl font-extrabold tracking-tight text-slate-900 dark:text-white sm:text-2xl">
Restro<span className="text-blue-600">ly</span>
</span>
</a>
</Link>

{/* Desktop Nav Links */}
<div className="hidden items-center gap-8 md:flex">
Expand Down Expand Up @@ -859,4 +863,4 @@ const [contactForm, setContactForm] = useState({
);
};

export default Landing;
export default Landing;