Spaces:
Sleeping
Sleeping
File size: 3,382 Bytes
dc11950 4dc66a3 aa63765 345b8ff dc11950 ef83e66 dc11950 4dc66a3 ef83e66 dc11950 ef83e66 aa63765 4dc66a3 dc11950 345b8ff dc11950 345b8ff ef83e66 aa63765 4dc66a3 dc11950 4dc66a3 dc11950 4dc66a3 dc11950 4dc66a3 dc11950 4dc66a3 aa63765 ef83e66 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 |
"use client";
import Link from "next/link";
import { AdminRulesPanel } from "@/components/admin-rules-panel";
import { AnalyticsPanel } from "@/components/analytics-panel";
import { ChatPanel } from "@/components/chat-panel";
import { FeatureGrid } from "@/components/feature-grid";
import { Footer } from "@/components/footer";
import { Hero } from "@/components/hero";
import { KnowledgeBasePanel } from "@/components/knowledge-base-panel";
import { TenantSelector } from "@/components/tenant-selector";
import { useTenant } from "@/contexts/TenantContext";
import {
canManageRules,
canViewAnalytics,
canIngestDocuments,
} from "@/lib/permissions";
function Navigation() {
const { role } = useTenant();
const navItems = [
{
label: "Data Ingestion",
href: "/ingestion",
visible: canIngestDocuments(role),
},
{ label: "Chat Bot", href: "/chat", visible: true }, // Chat is available to all
{
label: "Analytics",
href: "/analytics",
visible: canViewAnalytics(role),
},
{
label: "Admin Rule Ingestion",
href: "/admin-rules",
visible: canManageRules(role),
},
];
const visibleNavItems = navItems.filter((item) => item.visible);
return (
<nav className="flex flex-wrap gap-2">
{visibleNavItems.map((item) => (
<Link
key={item.href}
href={item.href}
className="rounded-full border border-white/15 px-4 py-2 text-xs font-semibold uppercase tracking-[0.2em] text-slate-200 transition hover:border-cyan-400 hover:text-white"
>
{item.label}
</Link>
))}
</nav>
);
}
export default function Home() {
const { role } = useTenant();
return (
<main className="mx-auto flex min-h-screen max-w-6xl flex-col gap-10 px-4 pb-16 pt-12 sm:px-6 lg:px-8">
<header className="flex flex-col gap-6 rounded-2xl border border-white/10 bg-white/5 px-6 py-6 text-slate-100 shadow-lg shadow-slate-950/40">
<div className="flex flex-wrap items-center justify-between gap-3 text-sm">
<div className="flex items-center gap-3 text-base font-semibold">
<span className="inline-flex h-10 w-10 items-center justify-center rounded-2xl bg-gradient-to-br from-sky-400 to-cyan-500 text-slate-950">
IC
</span>
IntegraChat Operator Console
</div>
<div className="flex flex-wrap items-center gap-3 text-xs uppercase tracking-[0.4em] text-slate-400">
FastAPI 路 MCP Servers 路 Celery 路 Next.js
</div>
</div>
<div className="flex flex-wrap items-center justify-between gap-4">
<Navigation />
<TenantSelector />
</div>
</header>
<Hero />
<FeatureGrid />
{canIngestDocuments(role) && (
<section id="data-ingestion" className="scroll-mt-28">
<KnowledgeBasePanel />
</section>
)}
<section id="chat-bot" className="scroll-mt-28">
<ChatPanel />
</section>
{canViewAnalytics(role) && (
<section id="analytics" className="scroll-mt-28">
<AnalyticsPanel />
</section>
)}
{canManageRules(role) && (
<section id="admin-rules" className="scroll-mt-28">
<AdminRulesPanel />
</section>
)}
<Footer />
</main>
);
}
|