Files
Ege Can Komur f88b76546c fix: blog empty state + proje detay yarı boş meta tablosu
Claude vision ile localhost'ta yapılan tarama sonrası 2 sorun:

1) Blog sayfası — henüz yazı yoksa empty state küçük bir kart olup
   altında ~1000px beyaz alan kalıyordu, footer çok aşağıdaydı.

   Çözüm: Empty state için zengin bir layout:
   - Gradient hero ('Blog yazılarımızı hazırlıyoruz' + 3 CTA:
     keşif görüşmesi / WhatsApp / Telefon)
   - 'Bu arada hizmetlerimize göz atın' başlıkla 6 hizmet grid
   - 'Site analiz raporu' lead magnet kartı
   Yazı geldiğinde otomatik normal grid'e döner.

2) Proje detay sayfası — sağ üstte 2 sütunlu meta card sadece
   'Yıl: 2025' gösteriyordu (client_name/industry/duration boş),
   yarı boş görünüyor + sağ tarafta büyük boşluk.

   Çözüm:
   - meta.length >= 2 → eski 2x2 grid card
   - meta.length === 1 → inline pill strip altta
   - meta yok → grid tek sütuna döner (lg:grid-cols-[1.4fr_1fr]
     conditional)

Claude vision ile 10 sayfa screenshot alındı (/tmp/kovak-screenshots).
Diğer sayfalar (anasayfa, hizmet detay, sektör, iletişim, vs)
tasarım açısından temiz görünüyor.
2026-05-20 19:07:26 +03:00

233 lines
9.4 KiB
TypeScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import Image from "next/image";
import Link from "next/link";
import type { Metadata } from "next";
import {
ArrowRight,
Calendar,
Sparkles,
MessageCircle,
Phone,
FileText,
} from "lucide-react";
import { SectionTitle } from "@/components/section-title";
import { Icon } from "@/components/icon";
import {
getSiteSettings,
listPublishedPosts,
listServices,
} from "@/lib/data";
import { buildMetadata } from "@/lib/seo";
import { siteConfig } from "@/lib/site-config";
export async function generateMetadata(): Promise<Metadata> {
return buildMetadata("/blog", {
title: "Blog",
description:
"Yazılım, web tasarım, SEO ve dijital pazarlama üzerine yazılar.",
});
}
export default async function BlogIndex() {
const [posts, services, settings] = await Promise.all([
listPublishedPosts(),
listServices(),
getSiteSettings(),
]);
const phoneRaw = settings?.contact_phone_raw ?? siteConfig.contact.phoneRaw;
const phone = settings?.contact_phone ?? siteConfig.contact.phone;
const wa = phoneRaw.replace(/[^\d]/g, "");
const waMessage = settings?.whatsapp_message ?? "";
const waHref = `https://wa.me/${wa}${
waMessage ? `?text=${encodeURIComponent(waMessage)}` : ""
}`;
// Empty state — site daha yeni, içerik yok
if (posts.length === 0) {
return (
<div className="mx-auto max-w-7xl px-6 py-20">
<SectionTitle
eyebrow="Blog"
title="Yazılım, tasarım ve büyüme üzerine"
description="Sektörden notlar, vaka çalışmaları ve teknik rehberler."
/>
{/* Coming soon hero */}
<div className="relative mt-14 overflow-hidden rounded-3xl bg-gradient-to-br from-[var(--navy)] via-[var(--sky-600)] to-[var(--sky)] p-12 text-center text-white shadow-xl shadow-[var(--navy)]/15">
<div
className="absolute inset-0 opacity-10"
style={{
backgroundImage:
"radial-gradient(circle at 1px 1px, white 1px, transparent 0)",
backgroundSize: "24px 24px",
}}
aria-hidden
/>
<div className="relative">
<span className="inline-flex items-center gap-2 rounded-full border border-white/30 bg-white/10 px-4 py-1.5 text-xs font-medium backdrop-blur">
<Sparkles className="size-3.5" />
Yakında
</span>
<h2 className="mt-5 text-3xl font-bold sm:text-4xl">
Blog yazılarımızı hazırlıyoruz
</h2>
<p className="mx-auto mt-4 max-w-xl text-base text-white/80">
Sektörden vaka çalışmaları, teknik rehberler ve sahada öğrendiklerimizi
kısa sürede burada paylaşmaya başlayacağız.
</p>
<div className="mt-8 flex flex-wrap items-center justify-center gap-3">
<Link
href="/iletisim"
className="inline-flex items-center gap-2 rounded-xl bg-white px-5 py-3 text-sm font-semibold text-[var(--navy)] transition hover:-translate-y-0.5 hover:bg-blue-50"
>
Ücretsiz keşif görüşmesi
<ArrowRight className="size-4" />
</Link>
<a
href={waHref}
target="_blank"
rel="noopener noreferrer"
className="inline-flex items-center gap-2 rounded-xl bg-[#25d366] px-5 py-3 text-sm font-semibold text-white transition hover:-translate-y-0.5 hover:bg-[#1ebe5d]"
>
<MessageCircle className="size-4" />
WhatsApp
</a>
<a
href={`tel:${phoneRaw}`}
className="inline-flex items-center gap-2 rounded-xl border border-white/30 bg-white/5 px-5 py-3 text-sm font-semibold text-white backdrop-blur transition hover:border-white/60"
>
<Phone className="size-4" />
{phone}
</a>
</div>
</div>
</div>
{/* Bu arada → Hizmetler grid */}
{services.length > 0 && (
<section className="mt-16">
<div className="flex items-end justify-between">
<SectionTitle
align="left"
eyebrow="Bu arada"
title="Hizmetlerimize göz atın"
description="Blog yazılarımızı beklerken sunduğumuz çözümleri keşfedin."
/>
<Link
href="/hizmetler"
className="hidden text-sm font-medium text-[var(--sky-600)] hover:text-[var(--navy)] sm:inline-flex"
>
Tümünü gör
</Link>
</div>
<div className="mt-10 grid gap-5 sm:grid-cols-2 lg:grid-cols-3">
{services.slice(0, 6).map((s) => (
<Link
key={s.slug}
href={`/hizmetler/${s.slug}`}
className="group relative overflow-hidden rounded-2xl border border-[var(--border)] bg-white p-6 transition-all duration-300 hover:-translate-y-1 hover:border-[var(--sky)]/40 hover:shadow-xl hover:shadow-[var(--navy)]/10"
>
<div className="flex size-12 items-center justify-center rounded-xl bg-gradient-to-br from-[var(--sky)] to-purple-500 text-white shadow-lg">
<Icon name={s.icon} className="size-5" />
</div>
<h3 className="mt-5 text-base font-bold text-[var(--navy)] group-hover:text-[var(--sky-600)]">
{s.title}
</h3>
<p className="mt-2 text-sm leading-relaxed text-[var(--muted)] line-clamp-2">
{s.description}
</p>
</Link>
))}
</div>
</section>
)}
{/* Lead magnet CTA */}
<section className="mt-16 rounded-2xl border border-dashed border-[var(--sky)]/40 bg-[var(--sky-50)]/40 p-8 sm:p-10">
<div className="flex flex-col items-start gap-6 sm:flex-row sm:items-center sm:justify-between">
<div>
<p className="text-xs font-semibold uppercase tracking-[0.18em] text-[var(--sky-600)]">
<FileText className="mr-1 inline size-3.5" />
Ücretsiz Rapor
</p>
<h3 className="mt-2 text-2xl font-bold text-[var(--navy)]">
Site analiz raporunuzu alın
</h3>
<p className="mt-2 max-w-xl text-sm text-[var(--muted)]">
Mevcut sitenizin SEO, hız, mobil ve dönüşüm performansını ücretsiz
değerlendirelim. 24 saat içinde detaylı rapor e-postanızda.
</p>
</div>
<Link
href="/site-analizi"
className="inline-flex items-center gap-2 rounded-xl bg-[var(--navy)] px-6 py-3 text-sm font-semibold text-white shadow-lg shadow-[var(--navy)]/20 transition hover:-translate-y-0.5 hover:bg-[var(--navy-700)]"
>
Ücretsiz raporumu istiyorum
<ArrowRight className="size-4" />
</Link>
</div>
</section>
</div>
);
}
// Normal grid — yazı varsa
return (
<div className="mx-auto max-w-7xl px-6 py-20">
<SectionTitle
eyebrow="Blog"
title="Yazılım, tasarım ve büyüme üzerine"
description="Sektörden notlar, vaka çalışmaları ve teknik rehberler."
/>
<div className="mt-14 grid gap-8 md:grid-cols-2 lg:grid-cols-3">
{posts.map((p) => (
<article
key={p.$id}
className="group overflow-hidden rounded-2xl border border-[var(--border)] bg-white transition hover:shadow-lg"
>
<Link href={`/blog/${p.slug}`}>
<div className="relative aspect-video overflow-hidden bg-[var(--navy-50)]">
{p.cover_image ? (
<Image
src={p.cover_image}
alt={p.title}
fill
sizes="(min-width: 1024px) 33vw, (min-width: 768px) 50vw, 100vw"
className="object-cover transition group-hover:scale-105"
/>
) : (
<div className="flex h-full items-center justify-center text-3xl font-bold text-[var(--navy)]/30">
{p.title.charAt(0)}
</div>
)}
</div>
<div className="p-6">
<p className="flex items-center gap-1.5 text-xs text-[var(--muted)]">
<Calendar className="size-3.5" />
{p.published_at
? new Date(p.published_at).toLocaleDateString("tr-TR")
: "—"}
</p>
<h3 className="mt-2 text-lg font-semibold text-[var(--navy)] group-hover:text-[var(--sky-600)]">
{p.title}
</h3>
{p.excerpt && (
<p className="mt-2 text-sm leading-relaxed text-[var(--muted)] line-clamp-3">
{p.excerpt}
</p>
)}
<span className="mt-4 inline-flex items-center gap-1 text-sm font-medium text-[var(--sky-600)]">
Devamını oku <ArrowRight className="size-3.5" />
</span>
</div>
</Link>
</article>
))}
</div>
</div>
);
}