174 lines
7.9 KiB
TypeScript
174 lines
7.9 KiB
TypeScript
import { Button } from "@/components/ui/button";
|
|
import { ArrowRight, CheckCircle2, LockKeyhole, Play, Sparkles } from "lucide-react";
|
|
import type { Lang } from "@/app/page";
|
|
|
|
const MANAGER_URL = "https://code.xinghanlab.com/";
|
|
|
|
const copy = {
|
|
en: {
|
|
eyebrow: "From idea to production software",
|
|
titleA: "One idea,",
|
|
titleB: "one AI development team.",
|
|
intro:
|
|
"Heicode organizes sub-Agnet teams, connects your code, documents, SK skills and cloud resources, and continuously carries work through requirements, development, testing, fixes, deployment and maintenance.",
|
|
primary: "Start with Heicode",
|
|
secondary: "Open Manager",
|
|
bullets: ["Input ideas in the client", "Bind resources in Manager", "Ship through Agnet"],
|
|
cockpit: "Heicode Task Cockpit",
|
|
project: "Small-team task management SaaS",
|
|
running: "Running",
|
|
inputLabel: "User input",
|
|
prompt:
|
|
"I want to build a small-team task management SaaS with login, projects, tasks, comments, notifications and admin, deployed to Azure.",
|
|
agents: [
|
|
["Product Agnet", "Requirements and acceptance", "Done"],
|
|
["Backend Agnet", "APIs and data model", "Building"],
|
|
["Frontend Agnet", "Pages and interaction", "Waiting for API"],
|
|
["Ops Agnet", "Deployment and observability", "Approval pending"],
|
|
],
|
|
approvalTitle: "Production deployment requires client approval",
|
|
approvalDesc:
|
|
"The secret vault will derive a 15-minute short-lived credential. Sub Agnets never receive long-term secrets.",
|
|
},
|
|
zh: {
|
|
eyebrow: "从想法到上线的软件生命周期平台",
|
|
titleA: "一个想法,",
|
|
titleB: "一支 AI 开发团队。",
|
|
intro:
|
|
"Heicode 组织子 Agnet,接入你的代码、文档、SK 和云资源,持续完成需求、开发、测试、修复、部署和后续维护。",
|
|
primary: "开始使用 Heicode",
|
|
secondary: "打开 Manager",
|
|
bullets: ["客户端输入想法", "Manager 绑定资源", "Agnet 交付部署"],
|
|
cockpit: "Heicode Task Cockpit",
|
|
project: "小团队任务管理 SaaS",
|
|
running: "运行中",
|
|
inputLabel: "用户输入",
|
|
prompt:
|
|
"我想做一个小团队任务管理 SaaS,需要登录、项目、任务、评论、通知和后台管理,希望部署到 Azure。",
|
|
agents: [
|
|
["Product Agnet", "需求和验收标准", "完成"],
|
|
["Backend Agnet", "API 与数据模型", "开发中"],
|
|
["Frontend Agnet", "页面与交互", "等待接口"],
|
|
["Ops Agnet", "部署与观测", "待审批"],
|
|
],
|
|
approvalTitle: "生产部署需要客户端审批",
|
|
approvalDesc: "密钥保管器将派生 15 分钟短期凭证,子 Agnet 不接触长期密钥。",
|
|
},
|
|
} satisfies Record<Lang, {
|
|
eyebrow: string;
|
|
titleA: string;
|
|
titleB: string;
|
|
intro: string;
|
|
primary: string;
|
|
secondary: string;
|
|
bullets: string[];
|
|
cockpit: string;
|
|
project: string;
|
|
running: string;
|
|
inputLabel: string;
|
|
prompt: string;
|
|
agents: string[][];
|
|
approvalTitle: string;
|
|
approvalDesc: string;
|
|
}>;
|
|
|
|
export function Hero({ lang }: { lang: Lang }) {
|
|
const t = copy[lang];
|
|
|
|
return (
|
|
<section className="relative overflow-hidden pt-28 pb-16 sm:pt-36 sm:pb-24">
|
|
<div className="pointer-events-none absolute inset-0 bg-[linear-gradient(to_right,color-mix(in_oklch,var(--foreground)_5%,transparent)_1px,transparent_1px),linear-gradient(to_bottom,color-mix(in_oklch,var(--foreground)_5%,transparent)_1px,transparent_1px)] bg-[size:42px_42px]" />
|
|
<div className="pointer-events-none absolute left-1/2 top-24 h-[420px] w-[70vw] -translate-x-1/2 rounded-full bg-primary/10 blur-[120px]" />
|
|
<div className="relative mx-auto max-w-7xl px-4 sm:px-6 lg:px-8">
|
|
<div className="grid gap-12 lg:grid-cols-[1.03fr_0.97fr] lg:items-center">
|
|
<div>
|
|
<div className="mb-6 inline-flex items-center gap-2 rounded-full border border-border bg-card/70 px-4 py-2 text-sm font-semibold shadow-sm backdrop-blur">
|
|
<Sparkles className="h-4 w-4 text-primary" />
|
|
{t.eyebrow}
|
|
</div>
|
|
|
|
<h1 className="max-w-4xl text-5xl font-black leading-[0.95] tracking-[-0.06em] sm:text-7xl lg:text-8xl">
|
|
{t.titleA}
|
|
<span className="block text-primary">{t.titleB}</span>
|
|
</h1>
|
|
|
|
<p className="mt-7 max-w-2xl text-lg leading-8 text-muted-foreground sm:text-xl">
|
|
{t.intro}
|
|
</p>
|
|
|
|
<div className="mt-9 flex flex-col gap-4 sm:flex-row">
|
|
<Button size="lg" className="h-12 rounded-full bg-foreground px-7 text-background hover:bg-foreground/90" asChild>
|
|
<a href={MANAGER_URL} target="_blank" rel="noreferrer">
|
|
{t.primary}
|
|
<ArrowRight className="h-4 w-4" />
|
|
</a>
|
|
</Button>
|
|
<Button variant="outline" size="lg" className="h-12 rounded-full border-foreground/20 bg-card/50 px-7" asChild>
|
|
<a href={MANAGER_URL} target="_blank" rel="noreferrer">
|
|
<Play className="h-4 w-4" />
|
|
{t.secondary}
|
|
</a>
|
|
</Button>
|
|
</div>
|
|
|
|
<div className="mt-8 grid max-w-2xl gap-3 text-sm text-muted-foreground sm:grid-cols-3">
|
|
{t.bullets.map((item) => (
|
|
<div key={item} className="flex items-center gap-2">
|
|
<CheckCircle2 className="h-4 w-4 text-accent" />
|
|
{item}
|
|
</div>
|
|
))}
|
|
</div>
|
|
</div>
|
|
|
|
<div className="relative">
|
|
<div className="absolute -left-6 -top-6 hidden h-24 w-24 rounded-full border border-primary/30 lg:block" />
|
|
<div className="rounded-[2rem] border border-foreground/10 bg-foreground p-3 shadow-2xl">
|
|
<div className="overflow-hidden rounded-[1.5rem] bg-[#10151d] text-white">
|
|
<div className="flex items-center justify-between border-b border-white/10 px-5 py-4">
|
|
<div>
|
|
<p className="text-xs uppercase tracking-[0.22em] text-white/45">{t.cockpit}</p>
|
|
<p className="mt-1 font-semibold">{t.project}</p>
|
|
</div>
|
|
<span className="rounded-full bg-emerald-400/15 px-3 py-1 text-xs font-semibold text-emerald-200">
|
|
{t.running}
|
|
</span>
|
|
</div>
|
|
|
|
<div className="grid gap-3 p-5">
|
|
<div className="rounded-2xl bg-white/[0.06] p-4">
|
|
<p className="text-xs text-white/45">{t.inputLabel}</p>
|
|
<p className="mt-2 text-sm leading-6 text-white/85">{t.prompt}</p>
|
|
</div>
|
|
|
|
<div className="grid gap-3 sm:grid-cols-2">
|
|
{t.agents.map(([role, work, state]) => (
|
|
<div key={role} className="rounded-2xl border border-white/10 bg-white/[0.04] p-4">
|
|
<p className="font-semibold">{role}</p>
|
|
<p className="mt-1 text-xs text-white/50">{work}</p>
|
|
<p className="mt-4 text-xs font-semibold text-primary-foreground/90">{state}</p>
|
|
</div>
|
|
))}
|
|
</div>
|
|
|
|
<div className="rounded-2xl border border-amber-300/20 bg-amber-300/10 p-4">
|
|
<div className="flex items-start gap-3">
|
|
<LockKeyhole className="mt-0.5 h-5 w-5 text-amber-200" />
|
|
<div>
|
|
<p className="text-sm font-semibold text-amber-100">{t.approvalTitle}</p>
|
|
<p className="mt-1 text-xs leading-5 text-amber-100/65">
|
|
{t.approvalDesc}
|
|
</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
);
|
|
}
|