feat: add chatbox widget and dynamic nav links from dashboard API

- Add ChatboxWidget component (src/chatbox.jsx) with business hours check
- Update nav.jsx to fetch links dynamically from /api/public/links
- Wire ChatboxWidget into app.jsx
- Add chatbox.jsx script tag to index.html

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
khondokartowsif171
2026-05-24 21:09:53 +06:00
parent 488c63236c
commit 189362e78d
4 changed files with 255 additions and 8 deletions
+33 -8
View File
@@ -1,6 +1,16 @@
// Top nav — minimal, sticky, blurred
const DASHBOARD = 'https://aura.auraajenticai.cloud'
const NAV_FALLBACK = [
{ id: "work", label: "Services", url: "#work" },
{ id: "stack", label: "Stack", url: "#stack" },
{ id: "agents", label: "Agents", url: "#agents" },
{ id: "timeline", label: "Timeline", url: "#timeline" },
{ id: "contact", label: "Contact", url: "#contact" },
]
const Nav = ({ onCmdK, theme, onToggleTheme, accent, lang, onToggleLang }) => {
const [scrolled, setScrolled] = React.useState(false);
const [links, setLinks] = React.useState(NAV_FALLBACK);
React.useEffect(() => {
const onScroll = () => setScrolled(window.scrollY > 12);
@@ -8,13 +18,28 @@ const Nav = ({ onCmdK, theme, onToggleTheme, accent, lang, onToggleLang }) => {
return () => window.removeEventListener("scroll", onScroll);
}, []);
const links = [
{ id: "work", label: "Services" },
{ id: "stack", label: "Stack" },
{ id: "agents", label: "Agents" },
{ id: "timeline", label: "Timeline" },
{ id: "contact", label: "Contact" },
];
// Fetch nav links from Control Center API (stale-while-revalidate)
React.useEffect(() => {
const CACHE_KEY = 'aura_nav_links'
const CACHE_TTL = 5 * 60 * 1000 // 5 min
const cached = sessionStorage.getItem(CACHE_KEY)
if (cached) {
try {
const { data, ts } = JSON.parse(cached)
if (Date.now() - ts < CACHE_TTL) { setLinks(data.length ? data : NAV_FALLBACK); return }
} catch {}
}
fetch(`${DASHBOARD}/api/public/links?page=home`, { signal: AbortSignal.timeout(3000) })
.then(r => r.ok ? r.json() : null)
.then(data => {
if (Array.isArray(data) && data.length > 0) {
const mapped = data.map(l => ({ id: l.id, label: l.label, url: l.url }))
setLinks(mapped)
sessionStorage.setItem(CACHE_KEY, JSON.stringify({ data: mapped, ts: Date.now() }))
}
})
.catch(() => {})
}, []);
return (
<nav style={{
@@ -53,7 +78,7 @@ const Nav = ({ onCmdK, theme, onToggleTheme, accent, lang, onToggleLang }) => {
{/* Center links */}
<div style={{ display: "flex", gap: 4, alignItems: "center" }} className="nav-links">
{links.map(l => (
<a key={l.id} href={`#${l.id}`} style={{
<a key={l.id} href={l.url || `#${l.id}`} style={{
fontSize: 13.5,
color: "var(--text-dim)",
padding: "6px 12px",