Vollständige Next.js 15 Portfolio-Website mit: - Blog-System mit 100+ Artikeln - Supabase-Integration - Responsive Design mit Tailwind CSS - TypeScript-Konfiguration - Testing-Setup mit Vitest und Playwright Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
140 lines
5.6 KiB
TypeScript
140 lines
5.6 KiB
TypeScript
import { getTranslations, getLocale } from 'next-intl/server';
|
|
import Link from 'next/link';
|
|
import Image from 'next/image';
|
|
import { Calendar, Tag, ExternalLink } from 'lucide-react';
|
|
|
|
// Project data embedded directly for SSG
|
|
const projectsData = [
|
|
{
|
|
slug: 'ai-data-reader',
|
|
title: 'AI Document Reader',
|
|
excerpt: 'KI-gestützte Dokumentenanalyse mit OLLAMA und Python',
|
|
date: '2024-01',
|
|
technologies: ['Python', 'OLLAMA', 'FastAPI', 'React'],
|
|
category: 'AI Development',
|
|
},
|
|
{
|
|
slug: 'smart-warehouse',
|
|
title: 'Smart Warehouse RFID',
|
|
excerpt: 'RFID-basiertes Lagerverwaltungssystem mit IoT-Integration',
|
|
date: '2024-02',
|
|
technologies: ['Python', 'RFID', 'IoT', 'PostgreSQL'],
|
|
category: 'IoT',
|
|
},
|
|
{
|
|
slug: 'website-mit-ki',
|
|
title: 'Portfolio mit KI',
|
|
excerpt: 'Moderne Portfolio-Website mit KI-Integration',
|
|
date: '2024-03',
|
|
technologies: ['Next.js', 'TypeScript', 'Tailwind', 'Supabase'],
|
|
category: 'Full-Stack',
|
|
},
|
|
];
|
|
|
|
const Projects = async () => {
|
|
const t = await getTranslations('pages.home.projects');
|
|
const locale = await getLocale();
|
|
|
|
return (
|
|
<section id="projects" className="py-24">
|
|
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
|
<div className="flex justify-between items-center mb-12">
|
|
<h2 className="text-3xl font-bold text-zinc-100">
|
|
{t('title')}
|
|
</h2>
|
|
<Link
|
|
href={`/${locale}/portfolio`}
|
|
className="text-zinc-400 hover:text-white transition-colors duration-300"
|
|
>
|
|
{t('viewAll')}
|
|
</Link>
|
|
</div>
|
|
|
|
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
|
|
{projectsData.map((project) => (
|
|
<Link
|
|
key={project.slug}
|
|
href={`/${locale}/portfolio/${project.slug}`}
|
|
className="group relative block bg-zinc-900/50 backdrop-blur-sm
|
|
rounded-xl shadow-lg hover:shadow-2xl
|
|
ring-1 ring-zinc-800 hover:ring-zinc-700
|
|
transition-all duration-500 focus:outline-none focus:ring-2
|
|
focus:ring-zinc-600 focus:ring-offset-2 focus:ring-offset-zinc-950
|
|
transform hover:-translate-y-1"
|
|
>
|
|
<div className="relative overflow-hidden rounded-xl">
|
|
{/* Image Container */}
|
|
<div className="aspect-[16/9] w-full relative overflow-hidden bg-zinc-900">
|
|
<Image
|
|
src={`/images/projects/${project.slug}/cover.avif`}
|
|
alt={project.title}
|
|
fill
|
|
sizes="(max-width: 640px) 350px, (max-width: 768px) 400px, (max-width: 1024px) 550px, 400px"
|
|
className="object-cover transition-transform duration-700 group-hover:scale-110"
|
|
/>
|
|
</div>
|
|
|
|
{/* Content */}
|
|
<div className="relative -mt-2 p-6 bg-zinc-900 z-10">
|
|
<div className="flex items-center gap-4 mb-4 text-zinc-500">
|
|
{project.date && (
|
|
<div className="flex items-center gap-2 text-sm">
|
|
<Calendar className="h-4 w-4" />
|
|
<span>{project.date}</span>
|
|
</div>
|
|
)}
|
|
{project.technologies.length > 0 && (
|
|
<div className="flex items-center gap-2 text-sm">
|
|
<Tag className="h-4 w-4" />
|
|
<span>{project.technologies.length} Technologies</span>
|
|
</div>
|
|
)}
|
|
</div>
|
|
|
|
<h3 className="text-xl font-semibold text-white mb-3 group-hover:text-zinc-100 transition-colors duration-300">
|
|
{project.title}
|
|
</h3>
|
|
<p className="text-zinc-400 text-sm line-clamp-2 mb-4 group-hover:text-zinc-300 transition-colors duration-300">
|
|
{project.excerpt}
|
|
</p>
|
|
|
|
{/* Tags */}
|
|
<div className="flex flex-wrap gap-2">
|
|
{project.technologies.slice(0, 3).map((tag, tagIndex) => (
|
|
<span
|
|
key={tagIndex}
|
|
className="px-3 py-1 bg-zinc-800/50 text-sm text-zinc-400 rounded-full
|
|
ring-1 ring-zinc-700/50 group-hover:ring-zinc-600/50
|
|
group-hover:bg-zinc-800/70 group-hover:text-zinc-300
|
|
transition-all duration-300"
|
|
>
|
|
{tag}
|
|
</span>
|
|
))}
|
|
{project.technologies.length > 3 && (
|
|
<span className="text-sm text-zinc-600">
|
|
+{project.technologies.length - 3} more
|
|
</span>
|
|
)}
|
|
</div>
|
|
|
|
{/* Link Icon */}
|
|
<div className="absolute top-6 right-6 p-2.5 rounded-full
|
|
bg-zinc-800/60 backdrop-blur-sm ring-1 ring-zinc-700/50
|
|
opacity-0 group-hover:opacity-100
|
|
transform translate-y-2 group-hover:translate-y-0
|
|
transition-all duration-300">
|
|
<ExternalLink className="h-4 w-4 text-zinc-400" />
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</Link>
|
|
))}
|
|
</div>
|
|
</div>
|
|
</section>
|
|
);
|
|
};
|
|
|
|
export default Projects;
|