Harden onion boot flow and deepen site surfaces
Add persistent onion key backup and restore, improve startup resilience, and flesh out the major site verticals with richer navigation, search coverage, and operator documentation. Made-with: Cursor
This commit is contained in:
233
components/Navbar.tsx
Normal file
233
components/Navbar.tsx
Normal file
@@ -0,0 +1,233 @@
|
||||
"use client";
|
||||
|
||||
import { useState } from "react";
|
||||
import Link from "next/link";
|
||||
import { useWallet } from "@/contexts/WalletContext";
|
||||
import { useAccount } from "@/contexts/AccountContext";
|
||||
import { useCart } from "@/contexts/CartContext";
|
||||
|
||||
const Navbar = () => {
|
||||
const [isMenuOpen, setIsMenuOpen] = useState(false);
|
||||
const { isConnected, address, connect, disconnect, luxCredits, usdStoreCredit } = useWallet();
|
||||
const { user, hydrated } = useAccount();
|
||||
const { itemCount, hydrated: cartReady } = useCart();
|
||||
|
||||
const navItems = [
|
||||
{ label: "Sanctuary", href: "/sanctuary", icon: "🛡️" },
|
||||
{ label: "Market", href: "/market", icon: "📈" },
|
||||
{ label: "Vendors", href: "/vendors", icon: "🏪" },
|
||||
{ label: "Checkout", href: "/checkout", icon: "₿" },
|
||||
{ label: "Forum", href: "/forum", icon: "◆" },
|
||||
{ label: "Exchange", href: "/exchange", icon: "📰" },
|
||||
{ label: "Barter", href: "/barter", icon: "♻️" },
|
||||
{ label: "Vault", href: "/vault", icon: "🗝️" },
|
||||
{ label: "Wiki", href: "/hidden-wiki", icon: "📚" },
|
||||
{ label: "Atlas", href: "/darknet-atlas", icon: "🗺️" },
|
||||
{ label: "Syndicate", href: "/syndicate", icon: "🕸️" },
|
||||
{ label: "Void crawl", href: "/search", icon: "🔦" },
|
||||
{ label: "Mirrors", href: "/account/hidden-services", icon: "🧅" },
|
||||
];
|
||||
|
||||
const handleWalletClick = () => {
|
||||
if (isConnected) {
|
||||
disconnect();
|
||||
} else {
|
||||
connect();
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<nav className="glass fixed top-0 left-0 right-0 z-50 mx-auto mt-4 max-w-7xl rounded-2xl border border-white/10 px-6 py-4 backdrop-blur-xl">
|
||||
<div className="flex items-center justify-between">
|
||||
{/* Logo */}
|
||||
<div className="flex items-center gap-3">
|
||||
<div className="relative">
|
||||
<div className="h-10 w-10 rounded-full bg-gradient-to-br from-neon-cyan to-neon-purple p-0.5">
|
||||
<div className="h-full w-full rounded-full bg-background flex items-center justify-center">
|
||||
<span className="text-xl font-bold">⏣</span>
|
||||
</div>
|
||||
</div>
|
||||
<div className="absolute -inset-1 -z-10 animate-pulse rounded-full bg-neon-cyan blur-md opacity-30"></div>
|
||||
</div>
|
||||
<Link href="/" className="font-orbitron text-2xl font-bold tracking-tighter">
|
||||
Cyber<span className="text-neon-cyan">Lux</span>
|
||||
</Link>
|
||||
<span className="hidden rounded-full bg-muted px-3 py-1 text-xs font-medium text-neon-green sm:inline">
|
||||
v1.0 • ALPHA
|
||||
</span>
|
||||
</div>
|
||||
|
||||
{/* Desktop Navigation */}
|
||||
<div className="hidden max-w-lg flex-wrap items-center justify-end gap-x-3 gap-y-1 md:flex lg:max-w-2xl lg:gap-x-4 xl:max-w-none xl:flex-nowrap xl:gap-x-5">
|
||||
{navItems.map((item) => (
|
||||
<Link
|
||||
key={item.label}
|
||||
href={item.href}
|
||||
className="group relative text-sm font-medium text-foreground/80 transition-colors hover:text-neon-cyan"
|
||||
>
|
||||
<span className="mr-1 opacity-60">{item.icon}</span>
|
||||
{item.label}
|
||||
<span className="absolute -bottom-1 left-0 h-0.5 w-0 bg-gradient-to-r from-neon-cyan to-neon-purple transition-all group-hover:w-full"></span>
|
||||
</Link>
|
||||
))}
|
||||
</div>
|
||||
|
||||
{/* Actions */}
|
||||
<div className="flex items-center gap-3 md:gap-4">
|
||||
{cartReady ? (
|
||||
<Link
|
||||
href="/checkout"
|
||||
className="relative hidden rounded-full border border-white/10 px-3 py-2 text-sm text-foreground/80 hover:border-neon-cyan/40 hover:text-neon-cyan sm:inline-flex"
|
||||
title="Cart"
|
||||
>
|
||||
🛒
|
||||
{itemCount > 0 ? (
|
||||
<span className="absolute -right-1 -top-1 flex h-5 min-w-5 items-center justify-center rounded-full bg-neon-pink px-1 text-[10px] font-bold text-background">
|
||||
{itemCount > 99 ? "99+" : itemCount}
|
||||
</span>
|
||||
) : null}
|
||||
</Link>
|
||||
) : null}
|
||||
<div className="hidden md:flex items-center gap-3">
|
||||
<div className="flex items-center gap-2 rounded-full bg-white/5 px-4 py-2 border border-white/10">
|
||||
<span className="text-xs text-foreground/60">LUX</span>
|
||||
<span className="font-orbitron text-sm text-neon-green">{luxCredits.toLocaleString()}</span>
|
||||
</div>
|
||||
<div
|
||||
className="flex items-center gap-2 rounded-full bg-white/5 px-4 py-2 border border-neon-cyan/20"
|
||||
title="Verified Bitcoin deposit balance (USD)"
|
||||
>
|
||||
<span className="text-xs text-foreground/60">USD</span>
|
||||
<span className="font-orbitron text-sm text-neon-cyan">${usdStoreCredit.toFixed(2)}</span>
|
||||
</div>
|
||||
</div>
|
||||
{hydrated ? (
|
||||
user ? (
|
||||
<Link
|
||||
href="/dashboard"
|
||||
className="hidden items-center gap-2 rounded-full border border-neon-cyan/30 bg-neon-cyan/10 px-4 py-2 text-sm font-medium text-neon-cyan hover:bg-neon-cyan/20 sm:flex"
|
||||
>
|
||||
<span className="max-w-[8rem] truncate">{user.displayName}</span>
|
||||
</Link>
|
||||
) : (
|
||||
<>
|
||||
<Link
|
||||
href="/sign-in"
|
||||
className="hidden rounded-full border border-white/15 px-4 py-2 text-sm font-medium text-foreground/80 hover:border-neon-cyan/50 hover:text-neon-cyan sm:inline-flex"
|
||||
>
|
||||
Sign in
|
||||
</Link>
|
||||
<Link
|
||||
href="/sign-up"
|
||||
className="hidden rounded-full border border-neon-purple/35 bg-neon-purple/10 px-4 py-2 text-sm font-medium text-neon-purple hover:bg-neon-purple/20 md:inline-flex"
|
||||
>
|
||||
Register
|
||||
</Link>
|
||||
</>
|
||||
)
|
||||
) : null}
|
||||
<button
|
||||
onClick={handleWalletClick}
|
||||
className={`flex items-center gap-2 rounded-full px-4 py-2 font-medium transition-all ${isConnected
|
||||
? "bg-gradient-to-r from-neon-green to-neon-cyan text-background"
|
||||
: "glow-border text-neon-cyan hover:bg-white/5"
|
||||
}`}
|
||||
>
|
||||
<span className="text-lg">{isConnected ? "🟢" : "⚡"}</span>
|
||||
{isConnected ? `${address?.slice(0, 6)}...${address?.slice(-4)}` : "Connect Wallet"}
|
||||
</button>
|
||||
<button
|
||||
className="rounded-full bg-white/5 p-2 hover:bg-white/10"
|
||||
aria-label="Toggle menu"
|
||||
onClick={() => setIsMenuOpen(!isMenuOpen)}
|
||||
>
|
||||
<div className="h-5 w-5 space-y-1.5">
|
||||
<div className={`h-0.5 bg-neon-cyan transition-transform ${isMenuOpen ? "translate-y-2 rotate-45" : ""}`}></div>
|
||||
<div className={`h-0.5 bg-neon-purple transition-opacity ${isMenuOpen ? "opacity-0" : ""}`}></div>
|
||||
<div className={`h-0.5 bg-neon-pink transition-transform ${isMenuOpen ? "-translate-y-2 -rotate-45" : ""}`}></div>
|
||||
</div>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Mobile Menu */}
|
||||
{isMenuOpen && (
|
||||
<div className="glass mt-4 rounded-xl border border-white/10 p-4 backdrop-blur-xl md:hidden">
|
||||
<div className="mb-3 flex gap-2 border-b border-white/10 pb-3">
|
||||
{cartReady ? (
|
||||
<Link
|
||||
href="/checkout"
|
||||
className="relative flex-1 rounded-lg border border-white/15 py-2 text-center text-sm font-medium"
|
||||
onClick={() => setIsMenuOpen(false)}
|
||||
>
|
||||
🛒 Cart
|
||||
{itemCount > 0 ? (
|
||||
<span className="ml-1 rounded bg-neon-pink px-1.5 text-[10px] font-bold text-background">
|
||||
{itemCount}
|
||||
</span>
|
||||
) : null}
|
||||
</Link>
|
||||
) : null}
|
||||
{hydrated && user ? (
|
||||
<Link
|
||||
href="/dashboard"
|
||||
className="flex-1 rounded-lg bg-neon-cyan/15 py-2 text-center text-sm font-bold text-neon-cyan"
|
||||
onClick={() => setIsMenuOpen(false)}
|
||||
>
|
||||
Dashboard
|
||||
</Link>
|
||||
) : hydrated ? (
|
||||
<Link
|
||||
href="/sign-in"
|
||||
className="flex-1 rounded-lg border border-white/15 py-2 text-center text-sm font-medium"
|
||||
onClick={() => setIsMenuOpen(false)}
|
||||
>
|
||||
Sign in
|
||||
</Link>
|
||||
) : null}
|
||||
{hydrated && !user ? (
|
||||
<Link
|
||||
href="/sign-up"
|
||||
className="flex-1 rounded-lg border border-neon-purple/40 py-2 text-center text-sm text-neon-purple"
|
||||
onClick={() => setIsMenuOpen(false)}
|
||||
>
|
||||
Register
|
||||
</Link>
|
||||
) : null}
|
||||
</div>
|
||||
<div className="grid grid-cols-2 gap-3">
|
||||
{navItems.map((item) => (
|
||||
<Link
|
||||
key={item.label}
|
||||
href={item.href}
|
||||
className="flex items-center gap-2 rounded-lg bg-white/5 p-3 text-sm font-medium transition-colors hover:bg-white/10"
|
||||
onClick={() => setIsMenuOpen(false)}
|
||||
>
|
||||
<span className="text-lg">{item.icon}</span>
|
||||
{item.label}
|
||||
</Link>
|
||||
))}
|
||||
</div>
|
||||
<div className="mt-4 flex gap-3 border-t border-white/10 pt-4 text-xs">
|
||||
<Link
|
||||
href="/sanctuary"
|
||||
className="flex-1 rounded-lg border border-white/10 px-3 py-2 text-center text-foreground/70 hover:border-neon-cyan/40 hover:text-neon-cyan"
|
||||
onClick={() => setIsMenuOpen(false)}
|
||||
>
|
||||
Sanctuary
|
||||
</Link>
|
||||
<Link
|
||||
href="/account/hidden-services"
|
||||
className="flex-1 rounded-lg border border-white/10 px-3 py-2 text-center text-foreground/70 hover:border-neon-purple/40 hover:text-neon-purple"
|
||||
onClick={() => setIsMenuOpen(false)}
|
||||
>
|
||||
Onion map
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</nav>
|
||||
);
|
||||
};
|
||||
|
||||
export default Navbar;
|
||||
Reference in New Issue
Block a user