2025-11-06 12:02:10 +00:00
|
|
|
'use client';
|
|
|
|
|
|
2025-11-13 11:10:00 +00:00
|
|
|
import { motion, AnimatePresence } from "framer-motion";
|
2025-11-06 12:02:10 +00:00
|
|
|
import { Button } from "@/components/ui/button";
|
2025-11-23 21:13:18 +00:00
|
|
|
import { Heart, Menu, X, LogOut } from "lucide-react";
|
2025-11-06 12:02:10 +00:00
|
|
|
import { ThemeToggle } from "@/components/ThemeToggle";
|
|
|
|
|
import { useEffect, useState } from "react";
|
2025-11-12 00:28:29 +00:00
|
|
|
import { LoginDialog } from "@/components/LoginDialog";
|
2025-11-22 21:29:35 +00:00
|
|
|
import { useRouter, usePathname } from "next/navigation";
|
2025-11-12 12:33:36 +00:00
|
|
|
import Link from "next/link";
|
2025-11-13 11:10:00 +00:00
|
|
|
import { useAppTheme } from "@/components/ThemeProvider";
|
2025-11-23 21:13:18 +00:00
|
|
|
import { useAuth } from "@/hooks/useAuth";
|
|
|
|
|
import { toast } from "sonner";
|
2025-11-06 12:02:10 +00:00
|
|
|
|
|
|
|
|
export function Navbar() {
|
2025-11-13 11:10:00 +00:00
|
|
|
const { theme } = useAppTheme();
|
|
|
|
|
const isDark = theme === "dark";
|
2025-11-12 00:28:29 +00:00
|
|
|
const [loginDialogOpen, setLoginDialogOpen] = useState(false);
|
2025-11-13 11:10:00 +00:00
|
|
|
const [mobileMenuOpen, setMobileMenuOpen] = useState(false);
|
2025-11-12 00:28:29 +00:00
|
|
|
const router = useRouter();
|
2025-11-22 21:29:35 +00:00
|
|
|
const pathname = usePathname();
|
|
|
|
|
const isUserDashboard = pathname?.startsWith("/user/dashboard");
|
2025-11-23 21:13:18 +00:00
|
|
|
const isUserSettings = pathname?.startsWith("/user/settings");
|
|
|
|
|
const isUserRoute = pathname?.startsWith("/user/");
|
|
|
|
|
const { isAuthenticated, logout } = useAuth();
|
2025-11-06 12:02:10 +00:00
|
|
|
|
|
|
|
|
const scrollToSection = (id: string) => {
|
|
|
|
|
const element = document.getElementById(id);
|
|
|
|
|
if (element) {
|
|
|
|
|
element.scrollIntoView({ behavior: "smooth" });
|
2025-11-13 11:10:00 +00:00
|
|
|
setMobileMenuOpen(false); // Close mobile menu after navigation
|
2025-11-06 12:02:10 +00:00
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
2025-11-12 00:28:29 +00:00
|
|
|
const handleLoginSuccess = () => {
|
2025-11-23 13:29:31 +00:00
|
|
|
// Redirect to admin dashboard after successful login
|
|
|
|
|
router.push("/admin/dashboard");
|
2025-11-13 11:10:00 +00:00
|
|
|
setMobileMenuOpen(false);
|
2025-11-12 00:28:29 +00:00
|
|
|
};
|
|
|
|
|
|
2025-11-23 21:13:18 +00:00
|
|
|
const handleLogout = () => {
|
|
|
|
|
logout();
|
|
|
|
|
toast.success("Logged out successfully");
|
|
|
|
|
setMobileMenuOpen(false);
|
|
|
|
|
router.push("/");
|
|
|
|
|
};
|
|
|
|
|
|
2025-11-13 11:10:00 +00:00
|
|
|
// Close mobile menu when clicking outside
|
|
|
|
|
useEffect(() => {
|
|
|
|
|
if (mobileMenuOpen) {
|
|
|
|
|
document.body.style.overflow = 'hidden';
|
|
|
|
|
} else {
|
|
|
|
|
document.body.style.overflow = 'unset';
|
|
|
|
|
}
|
|
|
|
|
return () => {
|
|
|
|
|
document.body.style.overflow = 'unset';
|
|
|
|
|
};
|
|
|
|
|
}, [mobileMenuOpen]);
|
|
|
|
|
|
2025-11-06 12:02:10 +00:00
|
|
|
return (
|
|
|
|
|
<motion.nav
|
|
|
|
|
initial={{ y: -100 }}
|
|
|
|
|
animate={{ y: 0 }}
|
|
|
|
|
transition={{ duration: 0.5 }}
|
|
|
|
|
className="fixed top-0 left-0 right-0 z-50 border-b border-border/50"
|
|
|
|
|
style={{
|
|
|
|
|
backgroundColor: isDark ? '#1a1e26' : '#ffffff'
|
|
|
|
|
}}
|
|
|
|
|
>
|
2025-11-13 11:10:00 +00:00
|
|
|
<div className="container mx-auto px-3 sm:px-4">
|
|
|
|
|
<div className="flex items-center justify-between h-14 sm:h-16">
|
2025-11-12 12:33:36 +00:00
|
|
|
<motion.div
|
2025-11-13 11:10:00 +00:00
|
|
|
className="flex items-center gap-1.5 sm:gap-2"
|
2025-11-06 12:02:10 +00:00
|
|
|
whileHover={{ scale: 1.05 }}
|
|
|
|
|
whileTap={{ scale: 0.95 }}
|
|
|
|
|
>
|
2025-11-13 11:10:00 +00:00
|
|
|
<Link href="/" className="flex items-center gap-1.5 sm:gap-2">
|
|
|
|
|
<div className="bg-gradient-to-r from-rose-500 to-pink-600 p-1.5 sm:p-2 rounded-lg sm:rounded-xl">
|
|
|
|
|
<Heart className="h-4 w-4 sm:h-5 sm:w-5 text-white fill-white" />
|
2025-11-12 12:33:36 +00:00
|
|
|
</div>
|
2025-11-13 11:10:00 +00:00
|
|
|
<span className="font-bold text-sm sm:text-base md:text-lg bg-gradient-to-r from-rose-600 via-pink-600 to-orange-600 bg-clip-text text-transparent">
|
2025-11-14 13:05:05 +00:00
|
|
|
Attune Heart Therapy
|
2025-11-12 12:33:36 +00:00
|
|
|
</span>
|
|
|
|
|
</Link>
|
|
|
|
|
</motion.div>
|
2025-11-06 12:02:10 +00:00
|
|
|
|
2025-11-13 11:10:00 +00:00
|
|
|
{/* Desktop Navigation */}
|
2025-11-23 21:13:18 +00:00
|
|
|
{!isUserRoute && (
|
2025-11-22 21:29:35 +00:00
|
|
|
<div className="hidden lg:flex items-center gap-4 xl:gap-6">
|
|
|
|
|
<button
|
|
|
|
|
onClick={() => scrollToSection("about")}
|
|
|
|
|
className={`text-sm font-medium transition-colors cursor-pointer px-3 py-2 rounded-lg ${isDark ? 'text-gray-300 hover:text-white hover:bg-gray-800' : 'text-gray-700 hover:text-primary hover:bg-gray-100'}`}
|
|
|
|
|
>
|
|
|
|
|
About
|
|
|
|
|
</button>
|
|
|
|
|
<button
|
|
|
|
|
onClick={() => scrollToSection("services")}
|
|
|
|
|
className={`text-sm font-medium transition-colors cursor-pointer px-3 py-2 rounded-lg ${isDark ? 'text-gray-300 hover:text-white hover:bg-gray-800' : 'text-gray-700 hover:text-primary hover:bg-gray-100'}`}
|
|
|
|
|
>
|
|
|
|
|
Services
|
|
|
|
|
</button>
|
|
|
|
|
<button
|
|
|
|
|
onClick={() => scrollToSection("contact")}
|
|
|
|
|
className={`text-sm font-medium transition-colors cursor-pointer px-3 py-2 rounded-lg ${isDark ? 'text-gray-300 hover:text-white hover:bg-gray-800' : 'text-gray-700 hover:text-primary hover:bg-gray-100'}`}
|
|
|
|
|
>
|
|
|
|
|
Contact
|
|
|
|
|
</button>
|
|
|
|
|
</div>
|
|
|
|
|
)}
|
2025-11-06 12:02:10 +00:00
|
|
|
|
2025-11-13 11:10:00 +00:00
|
|
|
{/* Desktop Actions */}
|
|
|
|
|
<div className="hidden lg:flex items-center gap-2">
|
2025-11-23 21:13:18 +00:00
|
|
|
{!isAuthenticated && !isUserDashboard && (
|
2025-11-22 21:29:35 +00:00
|
|
|
<Button
|
|
|
|
|
size="sm"
|
|
|
|
|
variant="outline"
|
|
|
|
|
className={`hover:opacity-90 hover:scale-105 transition-all text-xs sm:text-sm ${isDark ? 'border-gray-700 text-gray-300 hover:bg-gray-800' : ''}`}
|
|
|
|
|
onClick={() => setLoginDialogOpen(true)}
|
|
|
|
|
>
|
|
|
|
|
Sign In
|
|
|
|
|
</Button>
|
|
|
|
|
)}
|
2025-11-06 12:02:10 +00:00
|
|
|
<ThemeToggle />
|
2025-11-23 21:13:18 +00:00
|
|
|
{!isUserDashboard && (
|
|
|
|
|
<Link
|
|
|
|
|
href="/book-now"
|
|
|
|
|
className={`text-sm font-medium transition-colors cursor-pointer px-3 py-2 rounded-lg hover:opacity-90 ${isDark ? 'text-gray-300 hover:text-white' : 'text-gray-700 hover:text-rose-600'}`}
|
|
|
|
|
>
|
|
|
|
|
Book-Now
|
|
|
|
|
</Link>
|
|
|
|
|
)}
|
|
|
|
|
{isAuthenticated && (
|
|
|
|
|
<Button
|
|
|
|
|
size="sm"
|
|
|
|
|
variant="outline"
|
|
|
|
|
className={`hover:opacity-90 hover:scale-105 transition-all text-xs sm:text-sm ${
|
|
|
|
|
isUserRoute
|
|
|
|
|
? 'bg-red-600 hover:bg-red-700 text-white border-red-600 hover:border-red-700'
|
|
|
|
|
: isDark
|
|
|
|
|
? 'border-gray-700 text-gray-300 hover:bg-gray-800'
|
|
|
|
|
: ''
|
|
|
|
|
}`}
|
|
|
|
|
onClick={handleLogout}
|
|
|
|
|
>
|
|
|
|
|
<LogOut className="w-4 h-4 mr-2" />
|
|
|
|
|
Logout
|
|
|
|
|
</Button>
|
|
|
|
|
)}
|
2025-11-06 12:02:10 +00:00
|
|
|
</div>
|
2025-11-13 11:10:00 +00:00
|
|
|
|
|
|
|
|
{/* Mobile Actions */}
|
|
|
|
|
<div className="flex lg:hidden items-center gap-1.5 sm:gap-2">
|
|
|
|
|
<ThemeToggle />
|
|
|
|
|
<Button
|
|
|
|
|
variant="ghost"
|
|
|
|
|
size="icon"
|
|
|
|
|
onClick={() => setMobileMenuOpen(!mobileMenuOpen)}
|
|
|
|
|
className="hover:bg-gray-100 dark:hover:bg-gray-800 h-9 w-9 sm:h-10 sm:w-10"
|
|
|
|
|
aria-label="Toggle menu"
|
|
|
|
|
>
|
|
|
|
|
{mobileMenuOpen ? (
|
|
|
|
|
<X className="h-5 w-5 sm:h-6 sm:w-6" />
|
|
|
|
|
) : (
|
|
|
|
|
<Menu className="h-5 w-5 sm:h-6 sm:w-6" />
|
|
|
|
|
)}
|
|
|
|
|
</Button>
|
|
|
|
|
</div>
|
2025-11-06 12:02:10 +00:00
|
|
|
</div>
|
|
|
|
|
</div>
|
2025-11-13 11:10:00 +00:00
|
|
|
|
|
|
|
|
{/* Mobile Menu */}
|
|
|
|
|
<AnimatePresence>
|
|
|
|
|
{mobileMenuOpen && (
|
|
|
|
|
<>
|
|
|
|
|
{/* Backdrop */}
|
|
|
|
|
<motion.div
|
|
|
|
|
initial={{ opacity: 0 }}
|
|
|
|
|
animate={{ opacity: 1 }}
|
|
|
|
|
exit={{ opacity: 0 }}
|
|
|
|
|
transition={{ duration: 0.2 }}
|
|
|
|
|
className="fixed inset-0 bg-black/50 z-40 lg:hidden"
|
|
|
|
|
onClick={() => setMobileMenuOpen(false)}
|
|
|
|
|
/>
|
|
|
|
|
|
|
|
|
|
{/* Mobile Menu Panel */}
|
|
|
|
|
<motion.div
|
|
|
|
|
initial={{ x: '100%' }}
|
|
|
|
|
animate={{ x: 0 }}
|
|
|
|
|
exit={{ x: '100%' }}
|
|
|
|
|
transition={{ type: 'spring', damping: 25, stiffness: 200 }}
|
|
|
|
|
className="fixed top-14 sm:top-16 right-0 bottom-0 w-[280px] sm:w-80 max-w-[85vw] z-50 lg:hidden overflow-y-auto"
|
|
|
|
|
style={{
|
|
|
|
|
backgroundColor: isDark ? '#1a1e26' : '#ffffff'
|
|
|
|
|
}}
|
|
|
|
|
>
|
|
|
|
|
<div className="flex flex-col p-4 sm:p-6 space-y-3 sm:space-y-4">
|
|
|
|
|
{/* Mobile Navigation Links */}
|
2025-11-23 21:13:18 +00:00
|
|
|
{!isUserRoute && (
|
2025-11-22 21:29:35 +00:00
|
|
|
<>
|
|
|
|
|
<button
|
|
|
|
|
onClick={() => scrollToSection("about")}
|
|
|
|
|
className={`text-left text-sm sm:text-base font-medium py-2.5 sm:py-3 px-3 sm:px-4 rounded-lg transition-colors ${isDark ? 'text-gray-300 hover:bg-gray-800' : 'text-gray-700 hover:bg-gray-100'}`}
|
|
|
|
|
>
|
|
|
|
|
About
|
|
|
|
|
</button>
|
|
|
|
|
<button
|
|
|
|
|
onClick={() => scrollToSection("services")}
|
|
|
|
|
className={`text-left text-sm sm:text-base font-medium py-2.5 sm:py-3 px-3 sm:px-4 rounded-lg transition-colors ${isDark ? 'text-gray-300 hover:bg-gray-800' : 'text-gray-700 hover:bg-gray-100'}`}
|
|
|
|
|
>
|
|
|
|
|
Services
|
|
|
|
|
</button>
|
|
|
|
|
<button
|
|
|
|
|
onClick={() => scrollToSection("contact")}
|
|
|
|
|
className={`text-left text-sm sm:text-base font-medium py-2.5 sm:py-3 px-3 sm:px-4 rounded-lg transition-colors ${isDark ? 'text-gray-300 hover:bg-gray-800' : 'text-gray-700 hover:bg-gray-100'}`}
|
|
|
|
|
>
|
|
|
|
|
Contact
|
|
|
|
|
</button>
|
|
|
|
|
</>
|
|
|
|
|
)}
|
2025-11-13 11:10:00 +00:00
|
|
|
|
|
|
|
|
<div className={`border-t pt-3 sm:pt-4 mt-3 sm:mt-4 space-y-2 sm:space-y-3 ${isDark ? 'border-gray-700' : 'border-gray-200'}`}>
|
2025-11-23 21:13:18 +00:00
|
|
|
{!isAuthenticated && !isUserDashboard && (
|
2025-11-22 21:29:35 +00:00
|
|
|
<Button
|
|
|
|
|
variant="outline"
|
|
|
|
|
className={`w-full justify-start text-sm sm:text-base ${isDark ? 'border-gray-700 text-gray-300 hover:bg-gray-800' : ''}`}
|
|
|
|
|
onClick={() => {
|
|
|
|
|
setLoginDialogOpen(true);
|
|
|
|
|
setMobileMenuOpen(false);
|
|
|
|
|
}}
|
|
|
|
|
>
|
|
|
|
|
Sign In
|
|
|
|
|
</Button>
|
|
|
|
|
)}
|
2025-11-23 21:13:18 +00:00
|
|
|
{!isUserDashboard && (
|
|
|
|
|
<Link
|
|
|
|
|
href="/book-now"
|
|
|
|
|
onClick={() => setMobileMenuOpen(false)}
|
|
|
|
|
className={`text-left text-sm sm:text-base font-medium py-2.5 sm:py-3 px-3 sm:px-4 rounded-lg transition-colors ${isDark ? 'text-gray-300 hover:bg-gray-800' : 'text-gray-700 hover:bg-gray-100'}`}
|
|
|
|
|
>
|
|
|
|
|
Book-Now
|
2025-11-13 11:10:00 +00:00
|
|
|
</Link>
|
2025-11-23 21:13:18 +00:00
|
|
|
)}
|
|
|
|
|
{isAuthenticated && (
|
|
|
|
|
<Button
|
|
|
|
|
variant="outline"
|
|
|
|
|
className={`w-full justify-start text-sm sm:text-base ${
|
|
|
|
|
isUserRoute
|
|
|
|
|
? 'bg-red-600 hover:bg-red-700 text-white border-red-600 hover:border-red-700'
|
|
|
|
|
: isDark
|
|
|
|
|
? 'border-gray-700 text-gray-300 hover:bg-gray-800'
|
|
|
|
|
: ''
|
|
|
|
|
}`}
|
|
|
|
|
onClick={() => {
|
|
|
|
|
handleLogout();
|
|
|
|
|
}}
|
|
|
|
|
>
|
|
|
|
|
<LogOut className="w-4 h-4 mr-2" />
|
|
|
|
|
Logout
|
|
|
|
|
</Button>
|
|
|
|
|
)}
|
2025-11-13 11:10:00 +00:00
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</motion.div>
|
|
|
|
|
</>
|
|
|
|
|
)}
|
|
|
|
|
</AnimatePresence>
|
2025-11-12 00:28:29 +00:00
|
|
|
|
|
|
|
|
{/* Login Dialog */}
|
|
|
|
|
<LoginDialog
|
|
|
|
|
open={loginDialogOpen}
|
|
|
|
|
onOpenChange={setLoginDialogOpen}
|
|
|
|
|
onLoginSuccess={handleLoginSuccess}
|
|
|
|
|
/>
|
2025-11-06 12:02:10 +00:00
|
|
|
</motion.nav>
|
|
|
|
|
);
|
|
|
|
|
}
|