113 lines
4.2 KiB
TypeScript
113 lines
4.2 KiB
TypeScript
import Link from 'next/link';
|
|
import Image from 'next/image';
|
|
import { BookOpen, Code, FileText, Terminal, Webhook } from 'lucide-react';
|
|
import type { BlogPost, RelatedDoc } from '../types';
|
|
import { formatDate } from '../utils';
|
|
|
|
interface BlogSidebarProps {
|
|
relatedArticles: BlogPost[];
|
|
relatedDocs: RelatedDoc[];
|
|
}
|
|
|
|
const iconMap: Record<string, React.ComponentType<{ className?: string }>> = {
|
|
book: BookOpen,
|
|
code: Code,
|
|
file: FileText,
|
|
terminal: Terminal,
|
|
webhook: Webhook,
|
|
};
|
|
|
|
export const BlogSidebar = ({
|
|
relatedArticles,
|
|
relatedDocs,
|
|
}: BlogSidebarProps) => {
|
|
return (
|
|
<div className="space-y-8">
|
|
{relatedDocs.length > 0 && (
|
|
<div>
|
|
<h4 className="text-xs font-bold text-gray-500 uppercase tracking-wider mb-4">
|
|
Related Docs
|
|
</h4>
|
|
<div className="space-y-3 text-sm">
|
|
{relatedDocs.map((doc) => {
|
|
const Icon = iconMap[doc.icon] || FileText;
|
|
return (
|
|
<Link
|
|
key={doc.href}
|
|
href={doc.href}
|
|
className="flex items-center gap-2 text-gray-600 hover:text-violet-500 transition-colors group"
|
|
>
|
|
<Icon className="w-[18px] h-[18px] text-gray-400 group-hover:text-violet-500" />
|
|
<span>{doc.title}</span>
|
|
</Link>
|
|
);
|
|
})}
|
|
</div>
|
|
</div>
|
|
)}
|
|
|
|
<div className="rounded-xl border border-gray-700 bg-slate-800 p-6 shadow-xl relative overflow-hidden group">
|
|
<div className="absolute inset-0 bg-gradient-to-br from-violet-500/20 to-transparent opacity-0 group-hover:opacity-100 transition-opacity duration-500 pointer-events-none" />
|
|
<div className="relative z-10">
|
|
<h4 className="font-bold text-white text-lg mb-2">
|
|
Build faster with Banatie
|
|
</h4>
|
|
<p className="text-sm text-gray-400 mb-6 leading-relaxed">
|
|
Integrate AI image generation into your app in minutes. Start for
|
|
free.
|
|
</p>
|
|
<Link
|
|
href="/#get-access"
|
|
className="block w-full rounded-lg bg-violet-500 px-4 py-2.5 text-center text-sm font-semibold text-white shadow-lg hover:bg-violet-600 transition-all transform hover:-translate-y-0.5"
|
|
>
|
|
Get API Key
|
|
</Link>
|
|
</div>
|
|
</div>
|
|
|
|
{relatedArticles.length > 0 && (
|
|
<div>
|
|
<h4 className="text-xs font-bold text-gray-500 uppercase tracking-wider mb-4">
|
|
Related Articles
|
|
</h4>
|
|
<div className="space-y-6">
|
|
{relatedArticles.map((article) => (
|
|
<Link
|
|
key={article.slug}
|
|
href={`/blog/${article.slug}`}
|
|
className="group block rounded-xl border border-gray-200 overflow-hidden bg-white hover:border-violet-500/50 transition-colors shadow-sm"
|
|
>
|
|
<div className="aspect-video w-full bg-gray-100 relative overflow-hidden">
|
|
{article.heroImage ? (
|
|
<Image
|
|
src={article.heroImage}
|
|
alt={article.title}
|
|
fill
|
|
className="object-cover group-hover:scale-105 transition-transform duration-500"
|
|
/>
|
|
) : (
|
|
<>
|
|
<div className="absolute inset-0 bg-gradient-to-br from-violet-500/10 to-pink-500/10 group-hover:scale-105 transition-transform duration-500" />
|
|
<div className="absolute inset-0 flex items-center justify-center text-violet-500/40">
|
|
<FileText className="w-10 h-10" />
|
|
</div>
|
|
</>
|
|
)}
|
|
</div>
|
|
<div className="p-4">
|
|
<h5 className="text-base font-semibold text-gray-900 group-hover:text-violet-500 transition-colors leading-tight mb-2">
|
|
{article.title}
|
|
</h5>
|
|
<p className="text-xs text-gray-500">
|
|
{formatDate(article.date)} · {article.readTime}
|
|
</p>
|
|
</div>
|
|
</Link>
|
|
))}
|
|
</div>
|
|
</div>
|
|
)}
|
|
</div>
|
|
);
|
|
};
|