All checks were successful
CI / go-lint (push) Has been skipped
CI / python-lint (push) Has been skipped
CI / nodejs-lint (push) Has been skipped
CI / test-go-consent (push) Successful in 39s
CI / test-python-voice (push) Successful in 37s
CI / test-bqas (push) Successful in 37s
Neue statische Website fuer Kinder (6-12 Jahre) mit 8 Holzprojekten, SVG-Illustrationen, Sicherheitshinweisen und kindgerechtem Design. Next.js 15 + Tailwind + Framer Motion. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
60 lines
1.8 KiB
TypeScript
60 lines
1.8 KiB
TypeScript
'use client'
|
|
|
|
import { useState } from 'react'
|
|
import { motion } from 'framer-motion'
|
|
import { ProjectCard } from '@/components/ProjectCard'
|
|
import { projects } from '@/lib/projects'
|
|
|
|
const filters = [
|
|
{ label: 'Alle', value: 0 },
|
|
{ label: 'Anfaenger', value: 1 },
|
|
{ label: 'Fortgeschritten', value: 2 },
|
|
{ label: 'Profi', value: 3 },
|
|
]
|
|
|
|
export default function ProjektePage() {
|
|
const [filter, setFilter] = useState(0)
|
|
const filtered = filter === 0 ? projects : projects.filter((p) => p.difficulty === filter)
|
|
|
|
return (
|
|
<div className="max-w-6xl mx-auto px-4 py-12">
|
|
<motion.div
|
|
initial={{ opacity: 0, y: -10 }}
|
|
animate={{ opacity: 1, y: 0 }}
|
|
className="text-center mb-10"
|
|
>
|
|
<h1 className="font-heading font-bold text-4xl mb-3">Alle Projekte</h1>
|
|
<p className="text-dark/60 text-lg">Waehle ein Projekt und leg los!</p>
|
|
</motion.div>
|
|
|
|
{/* Filter */}
|
|
<div className="flex justify-center gap-2 mb-10">
|
|
{filters.map((f) => (
|
|
<button
|
|
key={f.value}
|
|
onClick={() => setFilter(f.value as 0 | 1 | 2 | 3)}
|
|
className={`px-4 py-2 rounded-xl font-semibold text-sm transition-colors ${
|
|
filter === f.value
|
|
? 'bg-primary text-white'
|
|
: 'bg-white text-dark/60 hover:bg-primary/5'
|
|
}`}
|
|
>
|
|
{f.label}
|
|
</button>
|
|
))}
|
|
</div>
|
|
|
|
{/* Grid */}
|
|
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-6">
|
|
{filtered.map((p) => (
|
|
<ProjectCard key={p.slug} project={p} />
|
|
))}
|
|
</div>
|
|
|
|
{filtered.length === 0 && (
|
|
<p className="text-center text-dark/40 mt-12">Keine Projekte in dieser Kategorie.</p>
|
|
)}
|
|
</div>
|
|
)
|
|
}
|