Files
auraajenticai-main/src/nav.jsx
T
khondokartowsif171 ca12491a49 feat: add self-serve "Get Started" registration CTA to nav + hero
Visitors previously had no path to create a client account -- only a
Client Login link. Both CTAs now route through aura-auth's /register
with next= pointed at the client portal's service catalog.
2026-08-23 22:28:29 +06:00

337 lines
12 KiB
React

// Top nav — minimal, sticky, blurred — mobile-responsive
const NAV_LINKS = [
{ id: "services", label: "Services", labelBn: "সার্ভিস", url: "#/services" },
{ id: "case-studies", label: "Case Studies", labelBn: "কেস স্টাডি", url: "#/case-studies" },
{ id: "pricing", label: "Pricing", labelBn: "মূল্য", url: "#/pricing" },
{ id: "blog", label: "Blog", labelBn: "ব্লগ", url: "#/blog" },
{ id: "contact", label: "Contact", labelBn: "যোগাযোগ", url: "#/contact" },
]
const NAV_TXT = {
en: { search: "Search", getQuote: "Get a Quote", clientLogin: "Client Login", getStarted: "Get Started" },
bn: { search: "খুঁজুন", getQuote: "কোট নিন", clientLogin: "ক্লায়েন্ট লগইন", getStarted: "শুরু করুন" },
};
// Where a self-serve account should land right after signing up -- the client portal's own
// service catalog, not a blank dashboard. aura-auth's /register already reads and honors `next`.
const REGISTER_URL = "https://auth.auraajenticai.cloud/register?next=" + encodeURIComponent("https://client.auraajenticai.cloud/services");
const Nav = ({ onCmdK, theme, onToggleTheme, accent, lang, onToggleLang, route }) => {
const [scrolled, setScrolled] = React.useState(false);
const [menuOpen, setMenuOpen] = React.useState(false);
const links = NAV_LINKS;
const t = NAV_TXT[lang] || NAV_TXT.en;
const bn = lang === "bn";
React.useEffect(() => {
const onScroll = () => setScrolled(window.scrollY > 12);
window.addEventListener("scroll", onScroll, { passive: true });
return () => window.removeEventListener("scroll", onScroll);
}, []);
return (
<>
<nav style={{
position: "fixed",
top: 0,
left: 0,
right: 0,
zIndex: 50,
borderBottom: scrolled ? "1px solid var(--line)" : "1px solid transparent",
background: scrolled ? "color-mix(in srgb, var(--bg) 75%, transparent)" : "transparent",
backdropFilter: scrolled ? "blur(14px)" : "none",
WebkitBackdropFilter: scrolled ? "blur(14px)" : "none",
transition: "all 0.25s ease",
}}>
<div className="container" style={{
display: "flex",
alignItems: "center",
justifyContent: "space-between",
height: 64,
}}>
{/* Brand */}
<a href="#top" style={{ display: "flex", alignItems: "center", gap: 10, flexShrink: 0 }}>
<Icons.Logo size={26} />
<span style={{ fontWeight: 600, fontSize: 15, letterSpacing: "-0.01em" }}>{PORTFOLIO_DATA.brand.name}</span>
<span className="nav-badge" style={{
fontFamily: "var(--font-mono)",
fontSize: 11,
color: "var(--text-faint)",
padding: "2px 7px",
border: "1px solid var(--line)",
borderRadius: 999,
marginLeft: 4,
}}>v.2026</span>
</a>
{/* Center links — hidden on mobile */}
<div style={{ display: "flex", gap: 4, alignItems: "center" }} className="nav-links">
{links.map(l => {
const isActive = route === l.id;
return (
<a key={l.id} href={l.url || `#/${l.id}`} style={{
fontSize: 13.5,
color: isActive ? "var(--text)" : "var(--text-dim)",
background: isActive ? "var(--line)" : "transparent",
padding: "6px 12px",
borderRadius: 8,
transition: "all 0.15s",
fontWeight: isActive ? 500 : 400,
}}
onMouseEnter={e => { e.currentTarget.style.color = "var(--text)"; e.currentTarget.style.background = "var(--line)"; }}
onMouseLeave={e => {
e.currentTarget.style.color = isActive ? "var(--text)" : "var(--text-dim)";
e.currentTarget.style.background = isActive ? "var(--line)" : "transparent";
}}
>{bn && l.labelBn ? l.labelBn : l.label}</a>
);
})}
</div>
{/* Right — desktop */}
<div className="nav-right" style={{ display: "flex", alignItems: "center", gap: 8 }}>
<button onClick={onCmdK} className="nav-search-btn" style={{
display: "flex",
alignItems: "center",
gap: 8,
padding: "6px 8px 6px 12px",
background: "transparent",
border: "1px solid var(--line)",
borderRadius: 8,
color: "var(--text-dim)",
fontSize: 12.5,
}}>
<Icons.Search size={13} />
<span>{t.search}</span>
<kbd style={{
fontFamily: "var(--font-mono)",
fontSize: 10.5,
padding: "2px 5px",
border: "1px solid var(--line)",
borderRadius: 4,
color: "var(--text-faint)",
}}>⌘K</kbd>
</button>
<button onClick={onToggleTheme} aria-label="Toggle theme" style={{
width: 34, height: 34,
display: "grid", placeItems: "center",
background: "transparent",
border: "1px solid var(--line)",
borderRadius: 8,
color: "var(--text-dim)",
}}>
{theme === "dark" ? <Icons.Sun size={15} /> : <Icons.Moon size={15} />}
</button>
<button onClick={onToggleLang} className="nav-lang-btn" style={{
padding: "6px 10px",
background: "transparent",
border: "1px solid var(--line)",
borderRadius: 8,
color: "var(--text-dim)",
fontSize: 12,
fontWeight: 600,
cursor: "pointer",
letterSpacing: "0.04em",
}}>
{lang === "en" ? "বাং" : "EN"}
</button>
<a href="mailto:ceo@auraajenticai.cloud?subject=Project Quote" className="nav-quote-btn" style={{
padding: "7px 13px",
background: "transparent",
border: "1px solid var(--line)",
borderRadius: 8,
color: "var(--text-dim)",
fontSize: 13,
fontWeight: 500,
textDecoration: "none",
whiteSpace: "nowrap",
}}>
{t.getQuote}
</a>
<a href="https://auth.auraajenticai.cloud/login" className="nav-login-btn" style={{
padding: "8px 12px",
background: "transparent",
border: "1px solid var(--line)",
borderRadius: 8,
color: "var(--text-dim)",
fontSize: 13,
fontWeight: 500,
textDecoration: "none",
whiteSpace: "nowrap",
}}>
{t.clientLogin}
</a>
<a href={REGISTER_URL} className="nav-signup-btn" style={{
display: "flex",
alignItems: "center",
gap: 6,
padding: "8px 14px",
background: "var(--text)",
color: "var(--bg)",
fontSize: 13,
fontWeight: 500,
borderRadius: 8,
textDecoration: "none",
whiteSpace: "nowrap",
}}>
{t.getStarted} <Icons.Arrow size={13} />
</a>
</div>
{/* Hamburger — mobile only */}
<button
className="nav-hamburger"
onClick={() => setMenuOpen(o => !o)}
aria-label={menuOpen ? "Close menu" : "Open menu"}
style={{
display: "none",
width: 36, height: 36,
background: "transparent",
border: "1px solid var(--line)",
borderRadius: 8,
color: "var(--text-dim)",
alignItems: "center",
justifyContent: "center",
flexShrink: 0,
cursor: "pointer",
}}
>
{menuOpen ? (
<svg width="16" height="16" viewBox="0 0 16 16" fill="none">
<path d="M2 2l12 12M14 2L2 14" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round"/>
</svg>
) : (
<svg width="16" height="16" viewBox="0 0 16 16" fill="none">
<path d="M2 4h12M2 8h12M2 12h12" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round"/>
</svg>
)}
</button>
</div>
<style>{`
@media (max-width: 880px) {
.nav-links { display: none !important; }
}
@media (max-width: 640px) {
.nav-search-btn { display: none !important; }
.nav-quote-btn { display: none !important; }
.nav-badge { display: none !important; }
}
@media (max-width: 480px) {
.nav-login-btn { display: none !important; }
.nav-signup-btn { display: none !important; }
.nav-hamburger { display: flex !important; }
}
`}</style>
</nav>
{/* Mobile drawer */}
{menuOpen && (
<div style={{
position: "fixed",
top: 64,
left: 0,
right: 0,
zIndex: 49,
background: "color-mix(in srgb, var(--bg) 96%, transparent)",
backdropFilter: "blur(20px)",
WebkitBackdropFilter: "blur(20px)",
borderBottom: "1px solid var(--line)",
padding: "1rem 20px 1.5rem",
display: "flex",
flexDirection: "column",
gap: 2,
}}>
{links.map(l => (
<a
key={l.id}
href={l.url || `#${l.id}`}
onClick={() => setMenuOpen(false)}
style={{
fontSize: 15,
color: "var(--text-dim)",
padding: "12px 4px",
textDecoration: "none",
display: "block",
borderBottom: "1px solid var(--line)",
}}
>{bn && l.labelBn ? l.labelBn : l.label}</a>
))}
<div style={{ display: "flex", gap: 8, marginTop: 14, flexWrap: "wrap" }}>
<button onClick={() => { onToggleTheme(); setMenuOpen(false); }} style={{
padding: "8px 14px",
background: "transparent",
border: "1px solid var(--line)",
borderRadius: 8,
color: "var(--text-dim)",
fontSize: 13,
cursor: "pointer",
}}>
{theme === "dark" ? "Light" : "Dark"}
</button>
<button onClick={() => { onToggleLang(); setMenuOpen(false); }} style={{
padding: "8px 14px",
background: "transparent",
border: "1px solid var(--line)",
borderRadius: 8,
color: "var(--text-dim)",
fontSize: 13,
cursor: "pointer",
fontWeight: 600,
}}>
{lang === "en" ? "বাংলা" : "English"}
</button>
<a
href="mailto:ceo@auraajenticai.cloud?subject=Project Quote"
onClick={() => setMenuOpen(false)}
style={{
padding: "8px 14px",
background: "transparent",
border: "1px solid var(--line)",
borderRadius: 8,
color: "var(--text-dim)",
fontSize: 13,
textDecoration: "none",
}}
>{t.getQuote}</a>
<a
href="https://auth.auraajenticai.cloud/login"
onClick={() => setMenuOpen(false)}
style={{
padding: "8px 14px",
background: "transparent",
border: "1px solid var(--line)",
color: "var(--text-dim)",
fontSize: 13,
fontWeight: 500,
borderRadius: 8,
textDecoration: "none",
}}
>{t.clientLogin}</a>
<a
href={REGISTER_URL}
onClick={() => setMenuOpen(false)}
style={{
padding: "8px 14px",
background: "var(--text)",
color: "var(--bg)",
fontSize: 13,
fontWeight: 500,
borderRadius: 8,
textDecoration: "none",
}}
>{t.getStarted}</a>
</div>
</div>
)}
</>
);
};
window.Nav = Nav;