feat: render featured and secondary project cards dynamically from array

This commit is contained in:
Chneemann 2026-07-27 08:33:38 +02:00
parent 43b4d9494f
commit 38bd4d8162
4 changed files with 167 additions and 3 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 31 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 43 KiB

View file

@ -1,10 +1,13 @@
import Link from "next/link";
import Image from "next/image";
const PROJECTS = [ const PROJECTS = [
{ {
title: "DABubble", title: "DABubble",
type: "Web Application", type: "Web Application",
description: description:
"This App is a Slack Clone App. It revolutionizes team communication and collaboration with its intuitive interface, real-time messaging, and robust channel organization.", "This App is a Slack Clone App. It revolutionizes team communication and collaboration with its intuitive interface, real-time messaging, and robust channel organization.",
image: "/assets/projects/join.jpg", image: "/assets/projects/dabubble.png",
tags: [ tags: [
{ name: "Angular", featured: true }, { name: "Angular", featured: true },
{ name: "TypeScript", featured: true }, { name: "TypeScript", featured: true },
@ -19,7 +22,7 @@ const PROJECTS = [
type: "Full-Stack App", type: "Full-Stack App",
description: description:
"Task manager inspired by the Kanban System. Create and organize tasks using drag and drop functions, assign users and categories to ensure efficient management.", "Task manager inspired by the Kanban System. Create and organize tasks using drag and drop functions, assign users and categories to ensure efficient management.",
image: "/assets/projects/dabubble.png", image: "/assets/projects/join.png",
tags: [ tags: [
{ name: "Angular (TS)", featured: true }, { name: "Angular (TS)", featured: true },
{ name: "Django REST", featured: true }, { name: "Django REST", featured: true },
@ -35,7 +38,7 @@ const PROJECTS = [
type: "Full-Stack App", type: "Full-Stack App",
description: description:
"Video platform for sharing and discovering videos. Upload, view, and stream content in various quality levels, all within a user-friendly interface designed to enhance the video experience.", "Video platform for sharing and discovering videos. Upload, view, and stream content in various quality levels, all within a user-friendly interface designed to enhance the video experience.",
image: "/assets/projects/videoflix.jpg", image: "/assets/projects/videoflix.png",
tags: [ tags: [
{ name: "Angular (TS)", featured: true }, { name: "Angular (TS)", featured: true },
{ name: "Django REST", featured: true }, { name: "Django REST", featured: true },
@ -66,6 +69,167 @@ export default function Portfolio() {
Portfolio<span className="text-blue-500">.</span> Portfolio<span className="text-blue-500">.</span>
</h2> </h2>
</div> </div>
<div className="space-y-6">
{/* Featured Project Card */}
{featuredProject && (
<div className="group relative rounded-2xl border border-slate-700/60 bg-slate-900/90 backdrop-blur-md shadow-lg shadow-black/40 border-t-slate-600/50 hover:border-blue-500/50 hover:bg-slate-800/90 hover:shadow-2xl hover:shadow-blue-500/10 hover:-translate-y-0.5 transition-all duration-300 ease-out overflow-hidden grid md:grid-cols-12 items-center">
<div className="absolute -top-12 -right-12 w-32 h-32 bg-blue-500/15 rounded-full blur-xl group-hover:bg-blue-500/25 transition-all duration-500 pointer-events-none z-20" />
{/* Description */}
<div className="p-5 md:col-span-7 z-10 flex flex-col justify-between h-full">
<div>
<div className="flex items-center justify-between mb-2 pr-28">
<p className="text-xs font-mono text-blue-400">
// {featuredProject.type}
</p>
</div>
<h3 className="text-2xl font-bold text-white mb-3 flex items-center gap-2 group-hover:text-blue-400 transition-colors">
<span className="text-blue-500 font-mono text-lg">//</span>{" "}
{featuredProject.title}
</h3>
<p className="text-slate-300 text-sm leading-relaxed mb-6">
{featuredProject.description}
</p>
</div>
<div>
{/* Badges */}
<div className="flex flex-wrap gap-2 mb-6">
{featuredProject.tags.map((tag) => (
<span
key={tag.name}
className={`px-3 py-1.5 text-xs font-mono rounded-lg transition-all duration-200 cursor-default hover:-translate-y-0.5 shadow-sm ${
tag.featured
? "bg-blue-500/10 text-blue-300 border border-blue-500/40 shadow-blue-500/5 hover:bg-blue-500/20 hover:border-blue-400 hover:text-white"
: "bg-slate-800/60 text-slate-400 border border-slate-700/40 hover:border-slate-500 hover:text-slate-200 hover:bg-slate-800"
}`}
>
{tag.name}
</span>
))}
</div>
{/* Links */}
<div className="flex items-center gap-4 text-sm font-semibold">
{featuredProject.demoLink && (
<Link
href={featuredProject.demoLink}
target="_blank"
className="text-white bg-blue-600 hover:bg-blue-500 px-4 py-2 rounded-lg transition-colors inline-flex items-center gap-2 shadow-md shadow-blue-600/20"
>
Live Demo
</Link>
)}
{featuredProject.githubLink && (
<Link
href={featuredProject.githubLink}
target="_blank"
className="text-slate-400 hover:text-white transition-colors"
>
GitHub Repo
</Link>
)}
</div>
</div>
</div>
{/* Image */}
<div className="relative md:col-span-5 h-64 md:h-full min-h-260px overflow-hidden border-t md:border-t-0 md:border-l border-slate-800/60">
<Image
src={featuredProject.image}
alt={`${featuredProject.title} Vorschau`}
fill
sizes="(max-width: 768px) 100vw, 40vw"
className="object-cover object-top opacity-60 group-hover:opacity-80 group-hover:scale-105 transition-all duration-500 ease-out"
/>
<div className="absolute inset-0 bg-linear-to-t md:bg-linear-to-r from-slate-900/90 via-slate-900/30 to-transparent pointer-events-none" />
</div>
</div>
)}
{/* Secondary Projects Grid */}
<div className="grid md:grid-cols-2 gap-6">
{secondaryProjects.map((project) => (
<div
key={project.title}
className="group relative rounded-2xl border border-slate-700/60 bg-slate-900/90 backdrop-blur-md shadow-lg shadow-black/40 border-t-slate-600/50 hover:border-blue-500/50 hover:bg-slate-800/90 hover:shadow-2xl hover:shadow-blue-500/10 hover:-translate-y-0.5 transition-all duration-300 ease-out overflow-hidden flex flex-col justify-between"
>
<div className="absolute -top-12 -right-12 w-24 h-24 bg-blue-500/15 rounded-full blur-xl group-hover:bg-blue-500/25 transition-all duration-500 pointer-events-none" />
{/* Image */}
<div className="relative h-44 overflow-hidden border-b border-slate-800/60">
<Image
src={project.image}
alt={project.title}
fill
sizes="(max-width: 768px) 100vw, 50vw"
className="object-cover object-top opacity-60 group-hover:opacity-80 group-hover:scale-105 transition-all duration-500 ease-out"
/>
<div className="absolute inset-0 bg-linear-to-t from-slate-900/90 to-transparent pointer-events-none" />
</div>
{/* Description */}
<div className="p-5 flex-1 flex flex-col justify-between relative z-10">
<div>
<div className="flex items-center justify-between mb-1">
<p className="text-xs font-mono text-slate-500">
// {project.type}
</p>
</div>
<h3 className="text-lg font-bold text-white mb-2 flex items-center gap-2 group-hover:text-blue-400 transition-colors">
<span className="text-blue-500 font-mono text-sm">//</span>{" "}
{project.title}
</h3>
<p className="text-slate-400 text-sm mb-4 leading-relaxed">
{project.description}
</p>
</div>
<div>
{/* Badges */}
<div className="flex flex-wrap gap-2 mb-4">
{project.tags.map((tag) => (
<span
key={tag.name}
className={`px-3 py-1.5 text-xs font-mono rounded-lg transition-all duration-200 cursor-default hover:-translate-y-0.5 shadow-sm ${
tag.featured
? "bg-blue-500/10 text-blue-300 border border-blue-500/40 shadow-blue-500/5 hover:bg-blue-500/20 hover:border-blue-400 hover:text-white"
: "bg-slate-800/60 text-slate-400 border border-slate-700/40 hover:border-slate-500 hover:text-slate-200 hover:bg-slate-800"
}`}
>
{tag.name}
</span>
))}
</div>
{/* Links */}
<div className="grid grid-cols-2 pt-2 border-t border-slate-800/60">
{project.frontendLink && (
<Link
href={project.frontendLink}
target="_blank"
className="text-xs font-mono text-blue-400 hover:underline inline-flex items-center gap-1"
>
Code (Frontend)
</Link>
)}
{project.backendLink && (
<Link
href={project.backendLink}
target="_blank"
className="text-xs font-mono text-blue-400 hover:underline inline-flex items-center gap-1"
>
Code (Backend)
</Link>
)}
</div>
</div>
</div>
</div>
))}
</div>
</div>
</section> </section>
); );
} }