Files
heicode-mananger/website/components/roadmap.tsx
T

109 lines
4.2 KiB
TypeScript

import type { Lang } from "@/app/page";
const copy = {
en: {
eyebrow: "MVP to lifecycle",
title: "Prove the loop first, then expand the full lifecycle",
description:
"The real Agnet platform deployment API can arrive later. Manager payloads, manifests, audit trails, and the client approval loop must be ready first.",
phases: [
{
phase: "Current MVP",
description:
"Heicode, CodeGW, and OpenBao deploy separately. Resource bindings, Grants, manifests, and secret custody form the first closed loop. The client signs in only to Heicode.",
status: "Converging",
},
{
phase: "Next",
description:
"Expose user-side CodeGW model and usage views, close the client login and approval download path, and integrate the real Agnet deployment API.",
status: "Priority",
},
{
phase: "Long term",
description:
"Add automated maintenance, upgrade plans, and continuous cost and quality observation so development, deployment, and maintenance live in one lifecycle.",
status: "Product direction",
},
],
},
zh: {
eyebrow: "MVP to lifecycle",
title: "当前先证明闭环,再做完整生命周期",
description:
"真实 Agnet 平台部署 API 可以后置,但 Manager 侧 payload、manifest、审计和客户端闭环必须先准备好。",
phases: [
{
phase: "当前 MVP",
description: "Heicode、CodeGW、OpenBao 解耦部署;资源绑定、Grant、manifest 和密钥保管闭环;客户端只登录 Heicode。",
status: "正在收敛",
},
{
phase: "下一步",
description: "CodeGW 用户侧模型与用量展示、客户端登录审批下载闭环、Agnet 平台真实部署接口联调。",
status: "优先推进",
},
{
phase: "长期形态",
description: "自动维护、升级计划、成本和质量持续观测,把开发、部署、维护纳入同一个生命周期闭环。",
status: "产品方向",
},
],
},
} satisfies Record<Lang, {
eyebrow: string;
title: string;
description: string;
phases: Array<{ phase: string; description: string; status: string }>;
}>;
export function Roadmap({ lang }: { lang: Lang }) {
const t = copy[lang];
return (
<section className="py-20 sm:py-32">
<div className="mx-auto max-w-7xl px-4 sm:px-6 lg:px-8">
<div className="mx-auto max-w-2xl text-center">
<p className="text-sm font-bold tracking-widest text-primary uppercase">
{t.eyebrow}
</p>
<h2 className="mt-4 text-3xl font-black tracking-tight sm:text-5xl">
{t.title}
</h2>
<p className="mt-4 text-sm text-muted-foreground">
{t.description}
</p>
</div>
<div className="mt-16">
<div className="relative">
{/* Connection Line */}
<div className="absolute left-1/2 top-0 hidden h-full w-px -translate-x-1/2 bg-gradient-to-b from-primary/50 via-border to-border lg:block" />
<div className="grid gap-8 lg:grid-cols-3">
{t.phases.map((item, index) => (
<div key={item.phase} className="relative">
{/* Circle Indicator */}
<div className="mx-auto mb-6 flex h-16 w-16 items-center justify-center rounded-full border-2 border-primary/30 bg-background">
<span className="text-2xl font-black text-primary">{index + 1}</span>
</div>
<div className="rounded-[1.6rem] border border-border bg-card/60 p-6 text-center shadow-sm">
<span className="inline-block rounded-full bg-primary/10 px-3 py-1 text-xs font-semibold text-primary">
{item.status}
</span>
<h3 className="mt-4 text-xl font-bold">{item.phase}</h3>
<p className="mt-3 text-sm leading-relaxed text-muted-foreground">
{item.description}
</p>
</div>
</div>
))}
</div>
</div>
</div>
</div>
</section>
);
}