initial commit: project completion with proper gitignore
This commit is contained in:
187
components/WorksClient.tsx
Normal file
187
components/WorksClient.tsx
Normal file
@@ -0,0 +1,187 @@
|
||||
"use client";
|
||||
|
||||
import Image from "next/image";
|
||||
import { useState } from "react";
|
||||
import Link from "next/link";
|
||||
import { ArrowUpRight } from "lucide-react";
|
||||
import Footer from "@/components/Footer";
|
||||
|
||||
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>
|
||||
|
||||
<Footer />
|
||||
</main>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user