Files
Portfolio/src/components/sections/Projects.tsx
T
damjan_savicandClaude Opus 4.5 e1bbe5455d Initial commit: Portfolio Website
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>
2026-02-01 15:07:20 +01:00

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;