From 0a46933f6aefb963fbac9ace77d99651c20026d3 Mon Sep 17 00:00:00 2001 From: "2569718930@qq.com" <2569718930@qq.com> Date: Wed, 24 Jun 2026 16:41:13 +0800 Subject: [PATCH] Add public market brief content assets --- frontend/app/briefs/[city]/[date]/page.tsx | 129 +++++ frontend/app/briefs/page.tsx | 21 + frontend/app/methodology/[slug]/page.tsx | 85 ++++ frontend/app/methodology/page.tsx | 21 + frontend/app/sitemap.ts | 46 +- frontend/app/sources/[slug]/page.tsx | 89 ++++ frontend/app/sources/page.tsx | 21 + .../public-content/PublicContentAnalytics.tsx | 91 ++++ .../public-content/PublicContentPages.tsx | 467 ++++++++++++++++++ .../__tests__/publicContentAssets.test.ts | 110 +++++ frontend/content/public-content.ts | 413 ++++++++++++++++ frontend/lib/app-analytics.ts | 6 +- 12 files changed, 1496 insertions(+), 3 deletions(-) create mode 100644 frontend/app/briefs/[city]/[date]/page.tsx create mode 100644 frontend/app/briefs/page.tsx create mode 100644 frontend/app/methodology/[slug]/page.tsx create mode 100644 frontend/app/methodology/page.tsx create mode 100644 frontend/app/sources/[slug]/page.tsx create mode 100644 frontend/app/sources/page.tsx create mode 100644 frontend/components/public-content/PublicContentAnalytics.tsx create mode 100644 frontend/components/public-content/PublicContentPages.tsx create mode 100644 frontend/components/public-content/__tests__/publicContentAssets.test.ts create mode 100644 frontend/content/public-content.ts diff --git a/frontend/app/briefs/[city]/[date]/page.tsx b/frontend/app/briefs/[city]/[date]/page.tsx new file mode 100644 index 00000000..75c5bbf8 --- /dev/null +++ b/frontend/app/briefs/[city]/[date]/page.tsx @@ -0,0 +1,129 @@ +import type { Metadata } from "next"; +import { notFound } from "next/navigation"; +import { BriefDetailPageView } from "@/components/public-content/PublicContentPages"; +import { + PUBLIC_BRIEFS, + absolutePublicUrl, + briefPath, + getBrief, +} from "@/content/public-content"; + +type BriefPageParams = { + city: string; + date: string; +}; + +export function generateStaticParams() { + return PUBLIC_BRIEFS.map((brief) => ({ + city: brief.city, + date: brief.date, + })); +} + +export async function generateMetadata({ + params, +}: { + params: Promise; +}): Promise { + const { city, date } = await params; + const brief = getBrief(city, date); + + if (!brief) { + return { + title: "Brief not found", + }; + } + + const pathname = briefPath(brief); + + return { + title: brief.title, + description: brief.description, + alternates: { + canonical: pathname, + }, + openGraph: { + type: "article", + title: brief.title, + description: brief.description, + url: pathname, + publishedTime: brief.publishedAt, + modifiedTime: brief.updatedAt, + }, + twitter: { + card: "summary", + title: brief.title, + description: brief.description, + }, + }; +} + +export default async function BriefDetailPage({ + params, +}: { + params: Promise; +}) { + const { city, date } = await params; + const brief = getBrief(city, date); + + if (!brief) { + notFound(); + } + + const pathname = briefPath(brief); + const jsonLd = [ + { + "@context": "https://schema.org", + "@type": "Article", + headline: brief.title, + description: brief.description, + datePublished: brief.publishedAt, + dateModified: brief.updatedAt, + mainEntityOfPage: absolutePublicUrl(pathname), + author: { + "@type": "Organization", + name: "PolyWeather", + url: "https://polyweather.top", + }, + publisher: { + "@type": "Organization", + name: "PolyWeather", + url: "https://polyweather.top", + }, + about: [ + brief.cityName, + brief.market, + brief.settlementSource, + "DEB forecast methodology", + ], + }, + { + "@context": "https://schema.org", + "@type": "BreadcrumbList", + itemListElement: [ + { + "@type": "ListItem", + position: 1, + name: "Briefs", + item: absolutePublicUrl("/briefs"), + }, + { + "@type": "ListItem", + position: 2, + name: brief.cityName, + item: absolutePublicUrl(pathname), + }, + ], + }, + ]; + + return ( + <> +