171 lines
6.5 KiB
TypeScript
171 lines
6.5 KiB
TypeScript
import Link from 'next/link'
|
|
import { getTranslations } from 'next-intl/server'
|
|
import { GitHubTextStatsCard } from './GitHubTextStatsCard'
|
|
import { getGitHubInfoFromLinks } from '@/lib/github/badges'
|
|
|
|
interface ProjectSidebarProps {
|
|
project: {
|
|
id: string
|
|
name: string
|
|
nameEn?: string | null
|
|
slug: string
|
|
links: Array<{
|
|
id: string
|
|
type: string
|
|
url: string
|
|
title?: string | null
|
|
}>
|
|
}
|
|
locale: string
|
|
}
|
|
|
|
// Helper function to get icon for link type
|
|
function getLinkIcon(type: string): string {
|
|
switch (type.toUpperCase()) {
|
|
case 'WEBSITE':
|
|
return 'language'
|
|
case 'GITHUB':
|
|
return 'code'
|
|
case 'HUGGINGFACE':
|
|
return 'model_training'
|
|
case 'PAPER':
|
|
return 'description'
|
|
default:
|
|
return 'link'
|
|
}
|
|
}
|
|
|
|
export async function ProjectSidebar({ project, locale }: ProjectSidebarProps) {
|
|
const t = await getTranslations('project')
|
|
|
|
// 获取 GitHub 统计数据
|
|
const githubInfo = getGitHubInfoFromLinks(project.links)
|
|
|
|
return (
|
|
<aside className="space-y-8">
|
|
{/* Project Links Card */}
|
|
{project.links.length > 0 && (
|
|
<div className="bg-white dark:bg-surface-dark border-2 border-black dark:border-gray-600 p-6 shadow-brutal dark:shadow-brutal-dark">
|
|
<h3 className="font-display font-bold text-lg mb-6 uppercase border-b-2 border-primary pb-2 inline-block">
|
|
{t('projectLinks')}
|
|
</h3>
|
|
<div className="space-y-4">
|
|
{project.links.map((link) => {
|
|
const icon = getLinkIcon(link.type)
|
|
const labelMap: Record<string, string> = {
|
|
WEBSITE: t('officialWebsite'),
|
|
GITHUB: t('githubRepo'),
|
|
HUGGINGFACE: t('huggingface'),
|
|
PAPER: t('paper'),
|
|
}
|
|
const label = labelMap[link.type] || t('externalLinks')
|
|
return (
|
|
<a
|
|
key={link.id}
|
|
href={link.url}
|
|
target="_blank"
|
|
rel="noopener noreferrer"
|
|
className="flex items-center justify-between group p-3 border border-gray-200 dark:border-gray-700 hover:border-black dark:hover:border-white transition-colors bg-gray-50 dark:bg-gray-800"
|
|
>
|
|
<div className="flex items-center gap-3">
|
|
<span className="material-icons" aria-hidden="true">{icon}</span>
|
|
<span className="font-bold text-sm">{link.title || label}</span>
|
|
</div>
|
|
<span className="material-icons text-sm group-hover:translate-x-1 transition-transform" aria-hidden="true">
|
|
arrow_forward
|
|
</span>
|
|
</a>
|
|
)
|
|
})}
|
|
</div>
|
|
</div>
|
|
)}
|
|
|
|
{/* GitHub Statistics Card */}
|
|
{githubInfo.owner && githubInfo.repo && (
|
|
<GitHubTextStatsCard
|
|
stats={{
|
|
owner: githubInfo.owner,
|
|
repo: githubInfo.repo,
|
|
// 注意:目前使用徽章 URL,后续可以通过 API 获取实际文本数据
|
|
// 如需显示实际数字,需要使用 GitHub API 或服务端获取
|
|
stars: githubInfo.stars,
|
|
forks: githubInfo.forks,
|
|
issues: githubInfo.issues,
|
|
license: githubInfo.license
|
|
}}
|
|
labels={{
|
|
header: t('githubStatsTitle'),
|
|
starsTitle: t('githubStatsViewStars'),
|
|
forksTitle: t('githubStatsViewForks'),
|
|
issuesTitle: t('githubStatsViewIssues'),
|
|
licenseTitle: t('githubStatsViewLicense'),
|
|
}}
|
|
/>
|
|
)}
|
|
|
|
{/* CTA Card */}
|
|
<div className="bg-primary border-2 border-black p-6 relative overflow-hidden shadow-brutal dark:shadow-none group cursor-pointer hover:bg-yellow-400 transition-colors">
|
|
<div className="absolute top-0 right-0 w-20 h-20 bg-white opacity-20 transform rotate-45 translate-x-10 -translate-y-10"></div>
|
|
<div className="absolute bottom-0 left-0 w-16 h-16 bg-black opacity-10 rounded-full transform -translate-x-8 translate-y-8"></div>
|
|
<div className="relative z-10 text-center">
|
|
<div className="w-12 h-12 bg-white rounded-full border-2 border-black flex items-center justify-center mx-auto mb-4 group-hover:scale-110 transition-transform">
|
|
<span className="material-icons text-2xl" aria-hidden="true">rocket_launch</span>
|
|
</div>
|
|
<h3 className="font-display font-bold text-xl mb-2">{t('buildYourOwnAgent')}</h3>
|
|
<p className="text-sm font-medium mb-6">{t('buildAgentDesc')}</p>
|
|
<Link
|
|
href={`/${locale}/projects`}
|
|
className="block w-full bg-black text-white font-display font-bold py-3 text-sm uppercase hover:bg-gray-800 transition-colors shadow-none text-center"
|
|
>
|
|
{t('getStartedNow')}
|
|
</Link>
|
|
</div>
|
|
</div>
|
|
|
|
{/* Table of Contents */}
|
|
{locale === 'en' && (
|
|
<div className="sticky top-24 bg-background-light dark:bg-background-dark border border-gray-300 dark:border-gray-700 p-6 hidden lg:block">
|
|
<h3 className="font-display font-bold text-sm uppercase tracking-widest mb-4 text-gray-500 dark:text-gray-400">
|
|
{t('onThisPage')}
|
|
</h3>
|
|
<ul className="space-y-3 text-sm border-l-2 border-gray-200 dark:border-gray-700 pl-4">
|
|
<li>
|
|
<a
|
|
href="#overview"
|
|
className="text-black dark:text-white font-bold border-l-2 border-black dark:border-white -ml-[18px] pl-4 block"
|
|
>
|
|
{t('overview')}
|
|
</a>
|
|
</li>
|
|
<li>
|
|
<a
|
|
href="#features"
|
|
className="text-gray-600 dark:text-gray-400 hover:text-black dark:hover:text-white transition-colors block"
|
|
>
|
|
{t('keyFeatures')}
|
|
</a>
|
|
</li>
|
|
<li>
|
|
<a
|
|
href="#getting-started"
|
|
className="text-gray-600 dark:text-gray-400 hover:text-black dark:hover:text-white transition-colors block"
|
|
>
|
|
{t('gettingStarted')}
|
|
</a>
|
|
</li>
|
|
<li>
|
|
<a
|
|
href="#use-cases"
|
|
className="text-gray-600 dark:text-gray-400 hover:text-black dark:hover:text-white transition-colors block"
|
|
>
|
|
{t('useCases')}
|
|
</a>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
)}
|
|
</aside>
|
|
)
|
|
}
|