mirror of
https://github.com/Hmbown/DeepSeek-TUI.git
synced 2026-09-03 06:50:13 +08:00
107
web/app/[locale]/digest/page.tsx
Normal file
107
web/app/[locale]/digest/page.tsx
Normal file
@@ -0,0 +1,107 @@
|
||||
import Link from "next/link";
|
||||
// Bypassing the '@' alias to force TypeScript to find the file
|
||||
import { getEnv } from "../../../lib/kv";
|
||||
|
||||
// Define the exact structure of the Digest data to fix all the 'any' type errors
|
||||
interface DigestSection {
|
||||
heading: string;
|
||||
items: string[];
|
||||
}
|
||||
|
||||
interface WeeklyDigest {
|
||||
weekId: string;
|
||||
titleEn: string;
|
||||
titleZh: string;
|
||||
summaryEn: string;
|
||||
summaryZh: string;
|
||||
sections: DigestSection[];
|
||||
generatedAt: string;
|
||||
}
|
||||
|
||||
export const revalidate = 3600; // Cache page updates hourly
|
||||
|
||||
export default async function DigestArchivePage() {
|
||||
// 1. Get the correct project environment bindings
|
||||
const env = await getEnv();
|
||||
const kv = env.CURATED_KV;
|
||||
|
||||
// Fallback array if no data is found or if KV isn't active in dev
|
||||
let digests: WeeklyDigest[] = [];
|
||||
|
||||
if (kv) {
|
||||
try {
|
||||
// Fetch all weekly digest keys generated by the agent tasks
|
||||
const { keys } = await kv.list({ prefix: "digest:weekly-" });
|
||||
|
||||
if (keys && keys.length > 0) {
|
||||
const digestsRaw = await Promise.all(
|
||||
keys.map(async (k: { name: string }) => {
|
||||
const data = await kv.get(k.name);
|
||||
return data;
|
||||
})
|
||||
);
|
||||
|
||||
// Explicitly defining item types so TypeScript stops panicking
|
||||
digests = digestsRaw
|
||||
.filter((item: string | null): item is string => Boolean(item))
|
||||
.map((item: string) => JSON.parse(item) as WeeklyDigest)
|
||||
.sort((a: WeeklyDigest, b: WeeklyDigest) =>
|
||||
new Date(b.generatedAt).getTime() - new Date(a.generatedAt).getTime()
|
||||
);
|
||||
}
|
||||
} catch (e) {
|
||||
console.error("Error reading from KV:", e);
|
||||
}
|
||||
}
|
||||
|
||||
// Handle empty state gracefully
|
||||
if (digests.length === 0) {
|
||||
return (
|
||||
<div className="flex flex-col items-center justify-center py-20 text-center max-w-xl mx-auto px-4">
|
||||
<h1 className="text-3xl font-bold mb-4 tracking-tight">Community Digest</h1>
|
||||
<p className="text-gray-500 dark:text-gray-400">
|
||||
We are gathering this week's community updates. Check back soon!
|
||||
</p>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="max-w-4xl mx-auto py-12 px-6">
|
||||
<h1 className="text-4xl font-extrabold mb-2 tracking-tight">Weekly Community Updates</h1>
|
||||
<p className="text-gray-500 dark:text-gray-400 mb-8">Maintainer-approved summaries from CodeWhale</p>
|
||||
|
||||
<div className="space-y-12">
|
||||
{digests.map((digest: WeeklyDigest) => (
|
||||
<article key={digest.weekId} className="border border-gray-200 dark:border-gray-800 rounded-xl p-6 shadow-sm bg-white dark:bg-black">
|
||||
<header className="mb-6 border-b border-gray-100 dark:border-gray-900 pb-4">
|
||||
<span className="text-xs bg-blue-50 text-blue-600 dark:bg-blue-950/50 dark:text-blue-400 px-2.5 py-1 rounded-md font-mono uppercase">
|
||||
{digest.weekId}
|
||||
</span>
|
||||
<h2 className="text-2xl font-bold mt-3 text-gray-900 dark:text-gray-50">{digest.titleEn}</h2>
|
||||
<h3 className="text-xl text-gray-500 dark:text-gray-400 mt-1 font-medium">{digest.titleZh}</h3>
|
||||
</header>
|
||||
|
||||
<div className="mb-6 space-y-4">
|
||||
<p className="text-gray-700 dark:text-gray-300 leading-relaxed">{digest.summaryEn}</p>
|
||||
<p className="text-gray-500 dark:text-gray-400 leading-relaxed italic">{digest.summaryZh}</p>
|
||||
</div>
|
||||
|
||||
<div className="space-y-6">
|
||||
{digest.sections.map((section: DigestSection, idx: number) => (
|
||||
<section key={idx} className="border-l-2 border-gray-200 dark:border-gray-800 pl-4">
|
||||
<h4 className="font-bold text-lg mb-2 text-gray-900 dark:text-gray-100">{section.heading}</h4>
|
||||
<ul className="list-disc list-inside space-y-1 text-gray-600 dark:text-gray-400 font-mono text-sm">
|
||||
{section.items.map((item: string, itemIdx: number) => (
|
||||
<li key={itemIdx}>{item}</li>
|
||||
))}
|
||||
</ul>
|
||||
</section>
|
||||
))}
|
||||
</div>
|
||||
</article>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -1,6 +1,5 @@
|
||||
import Link from "next/link";
|
||||
import type { Locale } from "@/lib/i18n/config";
|
||||
import { FACTS } from "@/lib/facts.generated";
|
||||
import { Seal } from "./seal";
|
||||
import { Whale } from "./whale";
|
||||
import { LocaleSwitcher } from "./locale-switcher";
|
||||
@@ -11,6 +10,8 @@ const EN_LINKS = [
|
||||
{ href: "/en/runtime", label: "Runtime", cn: "集成" },
|
||||
{ href: "/en/docs", label: "Docs", cn: "文档" },
|
||||
{ href: "/en/feed", label: "Activity", cn: "动态" },
|
||||
/* ADDED NEW DIGEST ARCHIVE LINK HERE */
|
||||
{ href: "/en/digest", label: "Digest", cn: "摘要" },
|
||||
{ href: "/en/roadmap", label: "Roadmap", cn: "路线" },
|
||||
{ href: "/en/faq", label: "FAQ", cn: "问答" },
|
||||
{ href: "/en/contribute", label: "Contribute", cn: "参与" },
|
||||
@@ -21,6 +22,8 @@ const ZH_LINKS = [
|
||||
{ href: "/zh/runtime", label: "集成", cn: "" },
|
||||
{ href: "/zh/docs", label: "文档", cn: "" },
|
||||
{ href: "/zh/feed", label: "动态", cn: "" },
|
||||
/* ADDED NEW ZH DIGEST ARCHIVE LINK HERE */
|
||||
{ href: "/zh/digest", label: "每周摘要", cn: "" },
|
||||
{ href: "/zh/roadmap", label: "路线图", cn: "" },
|
||||
{ href: "/zh/faq", label: "常见问题", cn: "" },
|
||||
{ href: "/zh/contribute", label: "参与贡献", cn: "" },
|
||||
@@ -41,7 +44,7 @@ export function Nav({ locale = "en" }: { locale?: Locale }) {
|
||||
</div>
|
||||
<div className="flex items-center gap-4">
|
||||
<span className="hidden md:inline">codewhale.net</span>
|
||||
<span className="tabular">{FACTS.version ? `v${FACTS.version}` : "v0.8.x"}</span>
|
||||
<span className="tabular">v0.8.x</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -99,4 +102,4 @@ export function Nav({ locale = "en" }: { locale?: Locale }) {
|
||||
</div>
|
||||
</header>
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user