186 lines
9.2 KiB
TypeScript
186 lines
9.2 KiB
TypeScript
"use client";
|
||
|
||
import Image from "next/image";
|
||
import { useState } from "react";
|
||
import Link from "next/link";
|
||
import { ArrowUpRight } from "lucide-react";
|
||
|
||
|
||
interface ProjectCardProps {
|
||
hero_image: string;
|
||
category: string;
|
||
title: string;
|
||
year: string;
|
||
client: string;
|
||
slug: string;
|
||
narrative_desc: string;
|
||
index: number;
|
||
}
|
||
|
||
function ProjectCard({ hero_image, category, title, year, client, slug, narrative_desc, index }: ProjectCardProps) {
|
||
// Alternating background colors like in the reference screenshot
|
||
const bgColors = ["bg-[#e2d1c1]", "bg-[#f9f6ef]", "bg-[#d8c7b8]", "bg-[#f5f1e8]"];
|
||
const bgColor = bgColors[index % bgColors.length];
|
||
|
||
return (
|
||
<Link href={`/works/${slug}`} className="group cursor-pointer block h-full">
|
||
<div className={`p-8 md:p-10 h-full flex flex-col transition-all duration-500 group-hover:translate-y-[-8px] ${bgColor}`}>
|
||
{/* 1. Image Area */}
|
||
<div className="relative aspect-[16/10] overflow-hidden mb-12 shadow-sm">
|
||
<Image
|
||
src={hero_image || "https://images.unsplash.com/photo-1536440136628-849c177e76a1"}
|
||
alt={title}
|
||
fill
|
||
className="object-cover transition-transform duration-1000 group-hover:scale-105"
|
||
/>
|
||
{/* Floating Title on Image like reference */}
|
||
<div className="absolute inset-0 flex flex-col items-center justify-center text-center p-6 bg-black/10">
|
||
<span className="text-[10px] tracking-[0.2em] uppercase text-white/80 mb-2">
|
||
{(() => {
|
||
let current = category;
|
||
try {
|
||
for (let i = 0; i < 3; i++) {
|
||
if (typeof current === 'string' && (current.trim().startsWith('[') || current.trim().startsWith('"'))) {
|
||
current = JSON.parse(current);
|
||
} else {
|
||
break;
|
||
}
|
||
}
|
||
return Array.isArray(current) ? current.join(" / ") : current;
|
||
} catch (e) {
|
||
return current;
|
||
}
|
||
})()}
|
||
</span>
|
||
<h3 className="editorial-headline text-3xl md:text-4xl text-white uppercase leading-tight drop-shadow-md">
|
||
{title}
|
||
</h3>
|
||
</div>
|
||
</div>
|
||
|
||
{/* 2. Description Area */}
|
||
<div className="flex-grow mb-12">
|
||
<p className="text-black/70 text-[13px] leading-[1.8] line-clamp-6 font-medium italic">
|
||
{narrative_desc || "Dijital dünyada markanızın sesini duyurmak ve özgün bir kimlik kazandırmak için tasarladığımız özel projelerimizden biri."}
|
||
</p>
|
||
</div>
|
||
|
||
{/* 3. Footer / Client Area */}
|
||
<div className="border-t border-black/10 pt-8 mt-auto">
|
||
<div className="flex justify-between items-end">
|
||
<div>
|
||
<span className="text-[9px] tracking-[0.2em] uppercase text-black/30 block mb-2">Müşteri</span>
|
||
<h4 className="editorial-headline text-3xl text-black uppercase opacity-80 group-hover:opacity-100 group-hover:text-primary transition-all">
|
||
{client || "Muğla Dijital"}
|
||
</h4>
|
||
</div>
|
||
<div className="text-[10px] font-black text-black/20 group-hover:text-primary transition-colors border border-black/5 px-2 py-1 rounded">
|
||
{year}
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</Link>
|
||
);
|
||
}
|
||
|
||
export default function WorksClient({ projects: initialProjects }: { projects: any[] }) {
|
||
const [activeCategory, setActiveCategory] = useState("Hepsi");
|
||
|
||
const categories = ["Hepsi", ...Array.from(new Set(initialProjects.flatMap(p => {
|
||
let current = p.category;
|
||
try {
|
||
for (let i = 0; i < 3; i++) {
|
||
if (typeof current === 'string' && (current.trim().startsWith('[') || current.trim().startsWith('"'))) {
|
||
current = JSON.parse(current);
|
||
} else {
|
||
break;
|
||
}
|
||
}
|
||
} catch (e) { }
|
||
return Array.isArray(current) ? current : (typeof current === 'string' && current ? [current] : []);
|
||
})))];
|
||
|
||
const filteredProjects = activeCategory === "Hepsi"
|
||
? initialProjects
|
||
: initialProjects.filter(p => {
|
||
let current = p.category;
|
||
try {
|
||
for (let i = 0; i < 3; i++) {
|
||
if (typeof current === 'string' && (current.trim().startsWith('[') || current.trim().startsWith('"'))) {
|
||
current = JSON.parse(current);
|
||
} else {
|
||
break;
|
||
}
|
||
}
|
||
} catch (e) { }
|
||
const cats = Array.isArray(current) ? current : (typeof current === 'string' && current ? [current] : []);
|
||
return cats.includes(activeCategory);
|
||
});
|
||
|
||
return (
|
||
<main className="min-h-screen bg-[#f5f5f0] text-black pt-24">
|
||
<section className="pt-24 pb-24 px-6 md:px-12">
|
||
<div className="max-w-7xl mx-auto">
|
||
{/* Header Area */}
|
||
<div className="mb-20">
|
||
<span className="text-[10px] tracking-[0.2em] uppercase text-black/40 block mb-6">Portfolyo</span>
|
||
<h1 className="editorial-headline text-4xl md:text-6xl lg:text-[5.5rem] text-black reveal opacity-0 uppercase">
|
||
Seçilmiş <br /> <span className="text-primary">Projeler.</span>
|
||
</h1>
|
||
<p className="text-black/40 text-[14px] max-w-2xl leading-relaxed mt-10 reveal reveal-delayed-1 opacity-0">
|
||
Markanızın dijital dünyadaki serüvenini profesyonel dokunuşlarla şekillendiriyoruz. Global vizyon, yerel strateji ile başarı hikayeleri yazıyoruz.
|
||
</p>
|
||
</div>
|
||
|
||
{/* Filter Section */}
|
||
<div className="flex flex-col md:flex-row justify-between items-center gap-8 mb-16 border-y border-black/10 py-8">
|
||
<div className="flex flex-wrap items-center gap-3">
|
||
{categories.map((cat) => (
|
||
<button
|
||
key={cat}
|
||
onClick={() => setActiveCategory(cat)}
|
||
className={`px-6 py-2 rounded-full text-[10px] font-bold uppercase tracking-widest transition-all border
|
||
${activeCategory === cat
|
||
? "bg-black text-white border-black"
|
||
: "text-black/40 border-black/10 hover:border-black/30 hover:text-black"
|
||
}`}
|
||
>
|
||
{cat}
|
||
</button>
|
||
))}
|
||
</div>
|
||
|
||
<div className="hidden md:block">
|
||
<span className="text-[10px] font-bold text-black/20 uppercase tracking-widest">
|
||
{filteredProjects.length} Proje
|
||
</span>
|
||
</div>
|
||
</div>
|
||
|
||
<div className="grid grid-cols-1 md:grid-cols-2 gap-x-8 gap-y-12">
|
||
{filteredProjects.map((project, index) => (
|
||
<ProjectCard key={index} {...project} index={index} />
|
||
))}
|
||
</div>
|
||
|
||
{filteredProjects.length === 0 && (
|
||
<div className="py-32 text-center border border-black/10">
|
||
<p className="text-black/40 text-sm">Bu kategoride henüz bir proje bulunmuyor.</p>
|
||
</div>
|
||
)}
|
||
|
||
{/* CTA Section Area */}
|
||
<div className="mt-32 border-t border-black/10 pt-24 text-center space-y-10">
|
||
<h2 className="editorial-headline text-3xl md:text-5xl text-black uppercase">Sıradaki Başarı Hikayesi <br /><span className="text-primary">Sizinle</span> Yazılsın.</h2>
|
||
<Link href="/contact" className="button-primary mx-auto">
|
||
Projeyi Başlat
|
||
<ArrowUpRight className="w-4 h-4" />
|
||
</Link>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
|
||
</main>
|
||
);
|
||
} |