Initial commit
Next.js + Express event management app for Hope Family Church.
This commit is contained in:
@@ -0,0 +1,89 @@
|
||||
"use client";
|
||||
|
||||
import Link from "next/link";
|
||||
import { usePathname } from "next/navigation";
|
||||
import { useAuth } from "@/hooks/useAuth";
|
||||
import { Home, Calendar, Phone, LogIn, UserPlus, LayoutDashboard, LogOut } from "lucide-react";
|
||||
import { useSiteSettings } from "@/contexts/SiteSettingsContext";
|
||||
import { brandColor } from "@/lib/siteConfig";
|
||||
|
||||
export const BottomNav = () => {
|
||||
const { user, loading: authLoading, logout } = useAuth();
|
||||
const pathname = usePathname();
|
||||
const { settings } = useSiteSettings();
|
||||
const accentColor = settings.accent_color || brandColor;
|
||||
|
||||
const handleLogout = () => {
|
||||
logout();
|
||||
window.location.href = "/";
|
||||
};
|
||||
|
||||
const isActive = (href: string) => {
|
||||
if (href.includes("#")) return false;
|
||||
if (href === "/") return pathname === "/";
|
||||
return pathname.startsWith(href);
|
||||
};
|
||||
|
||||
type NavItem = { href: string; label: string; icon: React.ElementType; onClick?: () => void };
|
||||
|
||||
// Auth items are only known once the token has been validated — omitting
|
||||
// them entirely while loading avoids a Login/Register -> Dashboard/Logout
|
||||
// flash on every load (see Navbar for the same pattern).
|
||||
const items: NavItem[] = [
|
||||
{ href: "/", label: "Home", icon: Home },
|
||||
{ href: "/events", label: "Events", icon: Calendar },
|
||||
{ href: "/#contact", label: "Contact", icon: Phone },
|
||||
...(authLoading
|
||||
? []
|
||||
: user
|
||||
? [
|
||||
{ href: "/dashboard", label: "Dashboard", icon: LayoutDashboard },
|
||||
{ href: "#", label: "Logout", icon: LogOut, onClick: handleLogout },
|
||||
]
|
||||
: [
|
||||
{ href: "/login", label: "Login", icon: LogIn },
|
||||
{ href: "/register", label: "Register", icon: UserPlus },
|
||||
]),
|
||||
];
|
||||
|
||||
return (
|
||||
<nav
|
||||
className="md:hidden fixed bottom-0 inset-x-0 z-50 bg-white border-t border-gray-200"
|
||||
style={{ paddingBottom: "env(safe-area-inset-bottom)" }}
|
||||
>
|
||||
<div className="flex items-stretch h-16">
|
||||
{items.map((item) => {
|
||||
const Icon = item.icon;
|
||||
const active = isActive(item.href);
|
||||
const color = active ? accentColor : "#9ca3af";
|
||||
|
||||
if (item.onClick) {
|
||||
return (
|
||||
<button
|
||||
key={item.label}
|
||||
onClick={item.onClick}
|
||||
className="flex-1 flex flex-col items-center justify-center gap-0.5 text-[10px] font-medium"
|
||||
style={{ color }}
|
||||
>
|
||||
<Icon size={22} strokeWidth={1.8} />
|
||||
<span>{item.label}</span>
|
||||
</button>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<Link
|
||||
key={item.href}
|
||||
href={item.href}
|
||||
className="flex-1 flex flex-col items-center justify-center gap-0.5 text-[10px] font-medium"
|
||||
style={{ color }}
|
||||
>
|
||||
<Icon size={22} strokeWidth={1.8} />
|
||||
<span>{item.label}</span>
|
||||
</Link>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
</nav>
|
||||
);
|
||||
};
|
||||
Reference in New Issue
Block a user