Files
kovakyazilim/components/footer.tsx
T
Ege Can Komur 1444aa3995 feat: anasayfa içeriği, iletişim ve sosyal medya yönetilebilir
Yeni site_settings tablosu (singleton, rowId='homepage'):
- Hero: badge, title, subtitle, 2 CTA (label+href), stats (JSON array)
- Section başlıkları: services/projects/testimonials eyebrow + title + description
- Alt CTA: title, description, button label+href
- Contact: phone (görünen + tel: ham), email, address, hafta içi/sonu saatleri
- Social: linkedin/instagram/twitter/facebook URL'leri
- Footer tagline

Mevcut hardcoded değerler seed edildi.

Admin:
- /admin/site sayfası eklendi (sidebar'a 'Site Ayarları' linki)
- Bölümlü tek form: Hero / Hizmetler / Projeler / Referanslar / Alt CTA / İletişim / Sosyal / Footer
- Stats için 'değer | etiket' satır formatı

Public bağlantılar:
- Hero component artık settings prop alıyor (fallback değerlerle)
- Anasayfa: tüm section başlıkları ve alt CTA settings'ten geliyor
- Header: telefon settings'ten
- Footer: tagline, adres, telefon, email, sosyal linkler settings'ten
  (sosyal link sadece dolu olanlar gösteriliyor)
- Footer'da hizmetler artık /hizmetler/[slug] detay sayfalarına bağlı
- İletişim sayfası: adres, telefon, email, saatler settings'ten

30 route üretiliyor.
2026-05-20 02:56:45 +03:00

121 lines
4.3 KiB
TypeScript
Raw 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 { Mail, MapPin, Phone } from "lucide-react";
import { LinkedinIcon, InstagramIcon, TwitterIcon } from "@/components/social-icons";
import { getSiteSettings, listServices } from "@/lib/data";
import { siteConfig } from "@/lib/site-config";
export async function Footer() {
const [settings, services] = await Promise.all([
getSiteSettings(),
listServices(),
]);
const tagline = settings?.footer_tagline ?? siteConfig.tagline;
const address = settings?.contact_address ?? siteConfig.contact.address;
const phone = settings?.contact_phone ?? siteConfig.contact.phone;
const phoneRaw = settings?.contact_phone_raw ?? siteConfig.contact.phoneRaw;
const email = settings?.contact_email ?? siteConfig.contact.email;
const socials = [
{ url: settings?.social_linkedin, label: "LinkedIn", Icon: LinkedinIcon },
{ url: settings?.social_instagram, label: "Instagram", Icon: InstagramIcon },
{ url: settings?.social_twitter, label: "Twitter / X", Icon: TwitterIcon },
].filter((s) => s.url);
const footerServices =
services.length > 0
? services.slice(0, 5)
: siteConfig.fallbackServices.slice(0, 5);
return (
<footer className="mt-24 border-t border-[var(--border)] bg-[var(--navy)] text-white">
<div className="mx-auto grid max-w-7xl gap-10 px-6 py-14 md:grid-cols-4">
<div>
<div className="flex items-center gap-3">
<Image
src="/logo.png"
alt={siteConfig.name}
width={48}
height={48}
className="brightness-0 invert"
/>
<span className="text-lg font-semibold">{siteConfig.name}</span>
</div>
<p className="mt-4 text-sm leading-relaxed text-white/70">{tagline}</p>
</div>
<div>
<h3 className="text-sm font-semibold uppercase tracking-wider text-white/80">
Hizmetler
</h3>
<ul className="mt-4 space-y-2 text-sm text-white/70">
{footerServices.map((s) => (
<li key={s.slug}>
<Link href={`/hizmetler/${s.slug}`} className="hover:text-white">
{s.title}
</Link>
</li>
))}
</ul>
</div>
<div>
<h3 className="text-sm font-semibold uppercase tracking-wider text-white/80">
İletişim
</h3>
<ul className="mt-4 space-y-3 text-sm text-white/70">
<li className="flex items-start gap-2">
<MapPin className="mt-0.5 size-4 shrink-0" />
<span>{address}</span>
</li>
<li className="flex items-center gap-2">
<Phone className="size-4 shrink-0" />
<a href={`tel:${phoneRaw}`} className="hover:text-white">
{phone}
</a>
</li>
<li className="flex items-center gap-2">
<Mail className="size-4 shrink-0" />
<a href={`mailto:${email}`} className="hover:text-white">
{email}
</a>
</li>
</ul>
</div>
{socials.length > 0 && (
<div>
<h3 className="text-sm font-semibold uppercase tracking-wider text-white/80">
Sosyal Medya
</h3>
<div className="mt-4 flex gap-3">
{socials.map(({ url, label, Icon }) => (
<a
key={label}
href={url as string}
target="_blank"
rel="noopener noreferrer"
aria-label={label}
className="flex size-9 items-center justify-center rounded-full bg-white/10 transition hover:bg-white/20"
>
<Icon className="size-4" />
</a>
))}
</div>
</div>
)}
</div>
<div className="border-t border-white/10">
<div className="mx-auto flex max-w-7xl flex-col items-center justify-between gap-2 px-6 py-5 text-xs text-white/60 md:flex-row">
<p>
© {new Date().getFullYear()} {siteConfig.name}. Tüm hakları saklıdır.
</p>
<p>Kocaeli, Türkiye</p>
</div>
</div>
</footer>
);
}